Back to index

lightning-sunbird  0.9+nobinonly
nsInstallDlg.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsSocket.h"
00041 #include "nsHTTPConn.h"
00042 #include "nsInstallDlg.h"
00043 #include "nsXInstaller.h"
00044 #include "nsXIEngine.h"
00045 #include <signal.h>
00046 #include <gtk/gtk.h>
00047 #include <errno.h>
00048 
00049 #define NUM_PS_ENTRIES 4
00050 
00051 typedef struct _DLProgress 
00052 {
00053     // progress widgets
00054     GtkWidget *vbox;
00055     GtkWidget *compName;
00056     GtkWidget *URL;
00057     GtkWidget *localPath;
00058     GtkWidget *status;
00059     GtkWidget *progBar;
00060 
00061     // progress info
00062     int       downloadedBytes;
00063     int       totalKB;
00064 } 
00065 DLProgress;
00066 
00067 static char             *sXPInstallEngine;
00068 static nsRunApp         *sRunAppList = NULL;
00069 static DLProgress       sDLProgress;
00070 
00071 static GtkWidget        *sDLTable = NULL;
00072 static GtkWidget        *sMsg0Label;
00073 static GtkWidget        *sTextBox;
00074 static GtkWidget        *sMajorLabel;
00075 static GtkWidget        *sMinorLabel;
00076 static GtkWidget        *sRateLabel;
00077 static GtkWidget        *sMajorProgBar;
00078 static GtkWidget        *sMinorProgBar;
00079 static GtkWidget        *sPSTextEntry[NUM_PS_ENTRIES];
00080 
00081 static int              bDownload = FALSE;
00082 static struct timeval   sDLStartTime;
00083 static int              bDLPause = FALSE;
00084 static int              bDLCancel = FALSE;
00085 
00086 nsInstallDlg::nsInstallDlg() :
00087     mMsg0(NULL)
00088 {
00089 }
00090 
00091 nsInstallDlg::~nsInstallDlg()
00092 {
00093     XI_IF_FREE(mMsg0);  
00094 }
00095 
00096 void
00097 nsInstallDlg::Back(GtkWidget *aWidget, gpointer aData)
00098 {
00099     DUMP("Back");
00100     if (aData != gCtx->idlg) return;
00101 
00102     // hide this notebook page
00103     gCtx->idlg->Hide(nsXInstallerDlg::BACKWARD_MOVE);
00104 
00105     // disconnect this dlg's nav btn signal handlers
00106     gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
00107     gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
00108 
00109     // show the last dlg
00110     if (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1))
00111         gCtx->cdlg->Show(nsXInstallerDlg::BACKWARD_MOVE);
00112     else
00113         gCtx->sdlg->Show(nsXInstallerDlg::BACKWARD_MOVE);
00114 }
00115 
00116 void
00117 nsInstallDlg::Next(GtkWidget *aWidget, gpointer aData)
00118 {
00119     DUMP("Next");
00120     int bCus;
00121     nsComponentList *comps = NULL;
00122 
00123     if (aData != gCtx->idlg) return;
00124 
00125     bCus = (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1));
00126     comps = gCtx->sdlg->GetSelectedSetupType()->GetComponents();
00127 
00128     // initialize progress bar cleanly
00129     int totalComps = 0;
00130     if (nsXIEngine::ExistAllXPIs(bCus, comps, &totalComps))
00131         bDownload = FALSE;
00132     else
00133         bDownload = TRUE;
00134 
00135     if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT) {
00136         gtk_progress_set_activity_mode(GTK_PROGRESS(sMajorProgBar), FALSE);
00137         gtk_progress_bar_update(GTK_PROGRESS_BAR(sMajorProgBar), (gfloat) 0);
00138         gtk_label_set_text(GTK_LABEL(sMajorLabel), "");
00139 
00140         if (bDownload)
00141         {
00142             InitDLProgress( TRUE );
00143 
00144             gtk_button_set_label(GTK_BUTTON(gCtx->back), gCtx->Res("PAUSE"));
00145             gtk_button_set_label(GTK_BUTTON(gCtx->next), gCtx->Res("RESUME"));
00146 
00147             gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
00148             gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
00149             gtk_signal_disconnect(GTK_OBJECT(gCtx->cancel), gCtx->cancelID);
00150 
00151             // disable resume button
00152             gtk_widget_set_sensitive(gCtx->next, FALSE);
00153 
00154             XI_GTK_UPDATE_UI();
00155 
00156             // hook up buttons with callbacks
00157             gCtx->backID = gtk_signal_connect(GTK_OBJECT(gCtx->back), "clicked",
00158                 GTK_SIGNAL_FUNC(DLPause), NULL);
00159             gCtx->nextID = gtk_signal_connect(GTK_OBJECT(gCtx->next), "clicked",
00160                 GTK_SIGNAL_FUNC(DLResume), NULL);
00161             gCtx->cancelID = gtk_signal_connect(GTK_OBJECT(gCtx->cancel), "clicked",
00162                 GTK_SIGNAL_FUNC(DLCancel), NULL);
00163         }
00164         else
00165         {
00166             gtk_widget_show(sMajorLabel);
00167             gtk_widget_show(sMajorProgBar);
00168 
00169             gtk_widget_set_sensitive(gCtx->back, FALSE);
00170             gtk_widget_set_sensitive(gCtx->next, FALSE);
00171             gtk_widget_set_sensitive(gCtx->cancel, FALSE);
00172         }
00173 
00174         gtk_widget_hide(sMsg0Label);
00175         gtk_widget_hide(sTextBox);
00176         if (bDownload && sDLTable)
00177             gtk_widget_hide(sDLTable);
00178         XI_GTK_UPDATE_UI();
00179     }
00180 
00181     PerformInstall();
00182     // mode auto has no call to gtk_main()
00183     if (gCtx->opt->mMode == nsXIOptions::MODE_DEFAULT)
00184       gtk_main_quit();
00185     
00186     return;
00187 }
00188 
00189 int
00190 nsInstallDlg::Parse(nsINIParser *aParser)
00191 {
00192     int err = OK;
00193     int bufsize = 0;
00194     char *showDlg = NULL;
00195     char secName[64];
00196     int i;
00197     char *app = NULL, *args = NULL;
00198     nsRunApp *newRunApp = NULL;
00199     
00200     /* compulsory keys */
00201     XI_ERR_BAIL(aParser->GetStringAlloc(DLG_START_INSTALL, XPINSTALL_ENGINE,
00202                 &sXPInstallEngine, &bufsize));
00203     if (bufsize == 0 || !sXPInstallEngine)
00204         return E_INVALID_KEY;
00205 
00206     /* optional keys */
00207     err = aParser->GetStringAlloc(DLG_START_INSTALL, TITLE, &mTitle, &bufsize);
00208     if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00209     if (bufsize == 0)
00210       XI_IF_FREE(mTitle); 
00211 
00212     aParser->GetStringAlloc(DLG_START_INSTALL, SUBTITLE, &mSubTitle, &bufsize);
00213     if (bufsize == 0)
00214       XI_IF_FREE(mSubTitle);
00215 
00216     bufsize = 0;
00217     err = aParser->GetStringAlloc(DLG_START_INSTALL, MSG0, &mMsg0, &bufsize);
00218     if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00219 
00220     bufsize = 5;
00221     XI_ERR_BAIL(aParser->GetStringAlloc(DLG_START_INSTALL, SHOW_DLG, 
00222                 &showDlg, &bufsize));
00223     if (bufsize != 0 && showDlg)
00224     {
00225         if (0 == strncmp(showDlg, "TRUE", 4))
00226             mShowDlg = nsXInstallerDlg::SHOW_DIALOG;
00227         else if (0 == strncmp(showDlg, "FALSE", 5))
00228             mShowDlg = nsXInstallerDlg::SKIP_DIALOG;
00229     }
00230 
00231     bufsize = 0;
00232     XI_ERR_BAIL(aParser->GetStringAlloc(DLG_START_INSTALL, TITLE, 
00233                 &mTitle, &bufsize));
00234     if (bufsize == 0)
00235         XI_IF_FREE(mTitle); 
00236 
00237     for (i = 0; err == OK; i++)
00238     {
00239         /* construct RunAppX section name */
00240         sprintf(secName, RUNAPPd, i);
00241         err = aParser->GetStringAlloc(secName, TARGET, &app, &bufsize);
00242         if (err == OK && bufsize > 0)
00243         {
00244             /* "args" is optional: this may return E_NO_KEY which we ignore */
00245             err = aParser->GetStringAlloc(secName, ARGS, &args, &bufsize);
00246             newRunApp = new nsRunApp(app, args);
00247             if (!newRunApp)
00248                 return E_MEM;
00249             err = AppendRunApp(newRunApp);
00250         }
00251     }
00252     err = OK; /* reset error since RunAppX sections are optional
00253                  and we could have gotten a parse error (E_NO_SEC) */
00254 
00255     return err;
00256 
00257 BAIL:
00258     return err;
00259 }
00260 
00261 int 
00262 nsInstallDlg::AppendRunApp(nsRunApp *aNewRunApp)
00263 {
00264     int err = OK;
00265     nsRunApp *currRunApp = NULL, *nextRunApp = NULL;
00266 
00267     /* param check */
00268     if (!aNewRunApp)
00269         return E_PARAM;
00270 
00271     /* special case: list is empty */
00272     if (!sRunAppList)
00273     {
00274         sRunAppList = aNewRunApp;
00275         return OK;
00276     }
00277 
00278     /* list has at least one element */
00279     currRunApp = sRunAppList;
00280     while (currRunApp)
00281     {
00282       if (!(nextRunApp = currRunApp->GetNext()))
00283         {
00284             currRunApp->SetNext(aNewRunApp);
00285             break;
00286         }
00287         currRunApp = nextRunApp;
00288     }
00289     return err;
00290 }
00291 
00292 void
00293 nsInstallDlg::FreeRunAppList()
00294 {
00295     nsRunApp *currRunApp = NULL, *nextRunApp = NULL;
00296 
00297     currRunApp = sRunAppList;
00298     while (currRunApp)
00299     {
00300         nextRunApp = currRunApp->GetNext();
00301         delete currRunApp;
00302         currRunApp = nextRunApp;
00303     }
00304 }
00305 
00306 void
00307 nsInstallDlg::RunApps()
00308 {
00309     nsRunApp *currRunApp = sRunAppList;
00310     char *argv[3], *dest;
00311     char apppath[MAXPATHLEN];
00312     extern NS_IMPORT_(char **) environ; /* globally available to all processes */
00313     int pid;
00314 
00315     dest = gCtx->opt->mDestination;
00316     if (chdir(dest) < 0) 
00317         fprintf(stderr,"chdir(%s): %s\n",dest,strerror(errno));
00318 
00319     while (currRunApp)
00320     {
00321         /* run application with supplied args */
00322         if ((pid = fork()) == 0)
00323         {
00324             /* child */
00325 
00326             if (*(dest + strlen(dest)) == '/') /* trailing slash */
00327                 sprintf(apppath, "%s%s", dest, currRunApp->GetApp());
00328             else                               /* no trailing slash */
00329                 sprintf(apppath, "%s/%s", dest, currRunApp->GetApp());
00330 
00331             argv[0] = apppath;
00332             argv[1] = currRunApp->GetArgs();
00333             argv[2] = NULL; /* null-terminate arg vector */
00334             execve(apppath, argv, environ);
00335 
00336             /* shouldn't reach this but in case execve fails we will */
00337             exit(0);
00338         }
00339         /* parent continues running to finish installation */
00340 
00341         currRunApp = currRunApp->GetNext();
00342     }
00343 }
00344 
00345 int
00346 nsInstallDlg::Show(int aDirection)
00347 {
00348     int err = OK;
00349     int totalComps = 0;
00350     GtkWidget *hbox = NULL;
00351     GtkWidget *vbox = NULL;
00352     GtkWidget *dlFrame, *dlCheckbox, *dlProxyBtn;
00353 
00354     XI_VERIFY(gCtx);
00355     XI_VERIFY(gCtx->notebook);
00356 
00357     if (mWidgetsInit == FALSE)
00358     {
00359         int bCus = 
00360             (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1));
00361         nsComponentList *comps = 
00362             gCtx->sdlg->GetSelectedSetupType()->GetComponents(); 
00363 
00364         // create a new table and add it as a page of the notebook
00365         mTable = gtk_table_new(5, 1, FALSE);
00366         gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), mTable, NULL);
00367         mPageNum = gtk_notebook_get_current_page(GTK_NOTEBOOK(gCtx->notebook));
00368         gtk_widget_show(mTable);
00369 
00370         // Show the text:
00371         // Setup will now install the following components:
00372         //  [component1]
00373         //  [component2]
00374         // to the following location:
00375         //  [install path]
00376         //
00377         // Click next to continue.
00378 
00379         sTextBox = gtk_vbox_new(FALSE, 6);
00380         gtk_container_set_border_width(GTK_CONTAINER(sTextBox), 12);
00381         gtk_table_attach(GTK_TABLE(mTable), sTextBox, 0, 1, 0, 1,
00382                          GtkAttachOptions(GTK_FILL | GTK_EXPAND),
00383                          GtkAttachOptions(0), 0, 0);
00384 
00385         GtkWidget *msg = gtk_label_new(gCtx->Res("WILL_INSTALL"));
00386         gtk_misc_set_alignment(GTK_MISC(msg), 0.0, 0.5);
00387         gtk_box_pack_start(GTK_BOX(sTextBox), msg, FALSE, FALSE, 0);
00388 
00389         nsComponent *currComp;
00390         for (currComp = comps->GetHead(); currComp;
00391              currComp = comps->GetNext()) {
00392 
00393           if (currComp->IsMainComponent() ||
00394               (!currComp->IsInvisible() && currComp->IsSelected())) {
00395             msg = gtk_label_new(currComp->GetDescShort());
00396             gtk_misc_set_alignment(GTK_MISC(msg), 0.0, 0.5);
00397             gtk_misc_set_padding(GTK_MISC(msg), 20, 0);
00398             gtk_box_pack_start(GTK_BOX(sTextBox), msg, FALSE, FALSE, 0);
00399           }
00400         }
00401 
00402         msg = gtk_label_new(gCtx->Res("TO_LOCATION"));
00403         gtk_misc_set_alignment(GTK_MISC(msg), 0.0, 0.5);
00404         gtk_box_pack_start(GTK_BOX(sTextBox), msg, FALSE, FALSE, 0);
00405 
00406         msg = gtk_label_new(gCtx->opt->mDestination);
00407         gtk_misc_set_alignment(GTK_MISC(msg), 0.0, 0.5);
00408         gtk_misc_set_padding(GTK_MISC(msg), 20, 0);
00409         gtk_box_pack_start(GTK_BOX(sTextBox), msg, FALSE, FALSE, 0);
00410 
00411         gtk_widget_show_all(sTextBox);
00412 
00413         if (!nsXIEngine::ExistAllXPIs(bCus, comps, &totalComps))
00414         {
00415             // insert a [ x ] heterogenous table
00416             sDLTable = gtk_table_new(2, 2, FALSE);
00417             gtk_widget_show(sDLTable);
00418 
00419             gtk_table_attach(GTK_TABLE(mTable), sDLTable, 0, 1, 1, 4, 
00420                 static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00421                      GtkAttachOptions(0), 20, 20);
00422             
00423             // download settings groupbox
00424             dlFrame = gtk_frame_new(gCtx->Res("DL_SETTINGS"));
00425             gtk_table_attach_defaults(GTK_TABLE(sDLTable), dlFrame, 0, 2, 0, 2);
00426             gtk_widget_show(dlFrame);
00427     
00428             // save installer modules checkbox and label
00429             dlCheckbox = gtk_check_button_new_with_label(
00430                             gCtx->Res("SAVE_MODULES"));
00431             gtk_widget_show(dlCheckbox);
00432             gtk_table_attach(GTK_TABLE(sDLTable), dlCheckbox, 0, 2, 0, 1,
00433                 GTK_FILL, GTK_FILL, 10, 20);
00434             gtk_signal_connect(GTK_OBJECT(dlCheckbox), "toggled",
00435                 GTK_SIGNAL_FUNC(SaveModulesToggled), NULL);
00436 
00437             // proxy settings button
00438             dlProxyBtn = gtk_button_new_with_label(gCtx->Res("PROXY_SETTINGS"));
00439             gtk_widget_show(dlProxyBtn);
00440             gtk_table_attach(GTK_TABLE(sDLTable), dlProxyBtn, 0, 1, 1, 2,
00441                 GTK_FILL, GTK_FILL, 10, 10);
00442             gtk_signal_connect(GTK_OBJECT(dlProxyBtn), "clicked",
00443                    GTK_SIGNAL_FUNC(ShowProxySettings), NULL);
00444         }
00445 
00446         // vbox with two widgets packed in: label0 / progmeter0 (major)
00447         vbox = gtk_vbox_new(FALSE, 0);
00448         hbox = gtk_hbox_new(FALSE, 0);
00449         sMajorLabel = gtk_label_new("");
00450         sRateLabel = gtk_label_new("");
00451         gtk_box_pack_start(GTK_BOX(hbox), sMajorLabel, FALSE, FALSE, 0);
00452         gtk_box_pack_start(GTK_BOX(hbox), sRateLabel, FALSE, FALSE, 0);
00453         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
00454         gtk_widget_show(hbox);
00455         gtk_widget_show(sMajorLabel);
00456         gtk_widget_show(sRateLabel);
00457 
00458         sMajorProgBar = gtk_progress_bar_new();
00459         gtk_box_pack_start(GTK_BOX(vbox), sMajorProgBar, FALSE, FALSE, 0);
00460         // gtk_widget_show(sMajorProgBar);
00461 
00462         gtk_table_attach(GTK_TABLE(mTable), vbox, 0, 1, 2, 3, 
00463             static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00464                      GtkAttachOptions(0), 20, 20);
00465         gtk_widget_show(vbox); 
00466 
00467         // vbox with two widgets packed in: label1 / progmeter1 (minor)
00468         vbox = gtk_vbox_new(FALSE, 0);
00469         hbox = gtk_hbox_new(FALSE, 0);
00470         sMinorLabel = gtk_label_new("");
00471         gtk_box_pack_start(GTK_BOX(hbox), sMinorLabel, FALSE, FALSE, 0);
00472         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
00473         gtk_widget_show(hbox);
00474         gtk_widget_show(sMinorLabel);
00475 
00476         sMinorProgBar = gtk_progress_bar_new();
00477         gtk_box_pack_start(GTK_BOX(vbox), sMinorProgBar, FALSE, FALSE, 0);
00478         // gtk_widget_show(sMinorProgBar); 
00479 
00480         gtk_table_attach(GTK_TABLE(mTable), vbox, 0, 1, 3, 4, 
00481             static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00482                      GtkAttachOptions(0), 20, 20);
00483         gtk_widget_show(vbox); 
00484 
00485         vbox = gtk_vbox_new(FALSE, 0);
00486         sMsg0Label = gtk_label_new(mMsg0);
00487         gtk_misc_set_alignment(GTK_MISC(sMsg0Label), 0.0, 1.0);
00488         gtk_misc_set_padding(GTK_MISC(sMsg0Label), 6, 12);
00489         gtk_box_pack_start(GTK_BOX(vbox), sMsg0Label, TRUE, TRUE, 0);
00490         gtk_table_attach(GTK_TABLE(mTable), vbox, 0, 1, 4, 5,
00491             static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00492                      GtkAttachOptions(GTK_FILL | GTK_EXPAND), 0, 0);
00493         gtk_widget_show(sMsg0Label);
00494         gtk_widget_show(vbox);
00495 
00496         
00497         mWidgetsInit = TRUE;
00498     }
00499     else
00500     {
00501         gtk_notebook_set_page(GTK_NOTEBOOK(gCtx->notebook), mPageNum);
00502         gtk_widget_show(mTable);
00503     }
00504 
00505     // <b>title</b>\0
00506     char *titleBuf = new char[strlen(mTitle) + 9];
00507     sprintf(titleBuf, "<b>%s</b>", mTitle);
00508 
00509     gtk_label_set_markup(GTK_LABEL(gCtx->header_title), titleBuf);
00510     gtk_label_set_text(GTK_LABEL(gCtx->header_subtitle), mSubTitle);
00511 
00512     delete[] titleBuf;
00513 
00514     // signal connect the buttons
00515     gCtx->backID = gtk_signal_connect(GTK_OBJECT(gCtx->back), "clicked",
00516                    GTK_SIGNAL_FUNC(nsInstallDlg::Back), gCtx->idlg);
00517     gCtx->nextID = gtk_signal_connect(GTK_OBJECT(gCtx->next), "clicked",
00518                    GTK_SIGNAL_FUNC(nsInstallDlg::Next), gCtx->idlg);
00519 
00520     if (gCtx->opt->mSetupType != (gCtx->sdlg->GetNumSetupTypes() - 1))
00521       gtk_widget_set_sensitive(gCtx->back, TRUE);
00522 
00523     // always change title of next button to "Install"
00524     gtk_button_set_label(GTK_BUTTON(gCtx->next), gCtx->Res("INSTALL"));
00525 
00526     return err;
00527 }
00528 
00529 int
00530 nsInstallDlg::Hide(int aDirection)
00531 {
00532     gtk_widget_hide(mTable);
00533 
00534     return OK;
00535 }
00536 
00537 int
00538 nsInstallDlg::ShowTable()
00539 {
00540     if (!mTable)
00541         return E_PARAM;
00542 
00543     gtk_widget_show(mTable);
00544 
00545     return OK;
00546 }
00547 
00548 int
00549 nsInstallDlg::HideTable()
00550 {
00551     if (!mTable)
00552         return E_PARAM;
00553 
00554     gtk_widget_hide(mTable);
00555 
00556     return OK;
00557 }
00558 
00559 int
00560 nsInstallDlg::SetMsg0(char *aMsg)
00561 {
00562     if (!aMsg)
00563         return E_PARAM;
00564 
00565     mMsg0 = aMsg;
00566 
00567     return OK;
00568 }
00569 
00570 char *
00571 nsInstallDlg::GetMsg0()
00572 {
00573     if (mMsg0)
00574         return mMsg0;
00575 
00576     return NULL;
00577 }
00578 
00579 int
00580 nsInstallDlg::PerformInstall()
00581 {
00582     DUMP("PerformInstall");
00583 
00584     int err = OK;
00585 
00586     // perform the installation
00587     nsXIEngine *engine = new nsXIEngine();
00588     if (!engine)
00589     {
00590         ErrorHandler(E_MEM);
00591         return E_MEM;
00592     }
00593 
00594     // get the component list for the current setup type
00595     nsComponentList *comps = NULL;
00596     nsComponent *xpiengine = NULL;
00597     int bCus = (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1));
00598     comps = gCtx->sdlg->GetSelectedSetupType()->GetComponents(); 
00599     if (!comps)
00600     {
00601         ErrorHandler(E_NO_COMPONENTS);
00602         return E_NO_COMPONENTS;
00603     }
00604     
00605     if (!sXPInstallEngine) return E_PARAM;
00606     xpiengine = comps->GetCompByArchive(sXPInstallEngine);
00607 
00608     // 1> download
00609     err = engine->Download(bCus, comps);
00610     if (err == E_DL_DROP_CXN)
00611     {
00612         ShowCxnDroppedDlg();
00613         if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
00614             DLPause(NULL, NULL);
00615         return err;
00616     }
00617     else if (err == E_CRC_FAILED)
00618     {
00619         ShowCRCFailedDlg();
00620         goto BAIL;
00621     }
00622     else if (err == E_DL_PAUSE || err == E_DL_CANCEL)
00623     {
00624         DUMP("Pause or Cancel pressed");
00625         goto BAIL;
00626     }
00627     else if (err != OK)
00628     {
00629         DUMP("dammit... hopped into the wrong hole!");
00630         ErrorHandler(err);
00631         goto BAIL;
00632     }
00633 
00634     // prepare install UI
00635     if (gCtx->opt->mMode != nsXIOptions::MODE_SILENT)
00636     {
00637         InitInstallProgress();
00638         HideNavButtons();
00639     }
00640 
00641     // 2> extract engine
00642     XI_ERR_BAIL(engine->Extract(xpiengine));
00643     
00644     // 3> install .xpis
00645     XI_ERR_BAIL(engine->Install(bCus, comps, gCtx->opt->mDestination));
00646 
00647     // delete xpis if user didn't request saving them
00648     if (bDownload && !gCtx->opt->mSaveModules)
00649     {
00650         engine->DeleteXPIs(bCus, comps);
00651     }
00652 
00653     // run all specified applications after installation
00654     if (sRunAppList)
00655     {
00656         if (gCtx->opt->mShouldRunApps)
00657             RunApps();
00658         FreeRunAppList();
00659     }
00660 
00661 BAIL:
00662     // destroy installer engine thread object
00663     XI_IF_DELETE(engine);
00664 
00665     return err;
00666 }
00667 
00668 void
00669 nsInstallDlg::XPIProgressCB(const char *aMsg, int aVal, int aMax)
00670 {
00671     if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT)
00672        return;
00673     // DUMP("XPIProgressCB");
00674 
00675     if (!aMsg)
00676         return;
00677 
00678     static int updates = 0;
00679     char msg[64];
00680     const char *colon = NULL, *lastSlash = NULL;
00681 
00682     if (aMax > 0)
00683     {
00684         // reset for next component
00685         if (updates)
00686             updates = 0;
00687 
00688         gfloat percent = (gfloat)((gfloat)aVal/(gfloat)aMax);
00689 #if 0
00690     printf("progress percent: %f\taVal: %d\taMax: %d\n", percent, aVal, aMax);
00691 #endif
00692         gtk_progress_set_activity_mode(GTK_PROGRESS(sMinorProgBar), FALSE);
00693         gtk_progress_bar_update(GTK_PROGRESS_BAR(sMinorProgBar), percent);
00694         gtk_widget_show(sMinorProgBar);
00695 
00696         sprintf(msg, gCtx->Res("PROCESSING_FILE"), aVal, aMax);
00697     }
00698     else
00699     {
00700         updates++;
00701         if (updates > 5)
00702             updates = 0;
00703         gfloat percent = (gfloat)((gfloat)updates/(gfloat)5);
00704 
00705         gtk_progress_set_activity_mode(GTK_PROGRESS(sMinorProgBar), TRUE);
00706         gtk_progress_bar_update(GTK_PROGRESS_BAR(sMinorProgBar), percent);
00707         gtk_widget_show(sMinorProgBar);
00708 
00709         /* tack on XPInstall action */
00710         memset(msg, 0, 64);
00711         colon = strchr(aMsg, ':');
00712         if (colon)
00713             strncpy(msg, aMsg, colon - aMsg);
00714 
00715         strncat(msg, " ", 1);
00716 
00717         /* tack on leaf name */
00718         lastSlash = strrchr(aMsg, '/');
00719         if (lastSlash)
00720             strncat(msg, lastSlash + 1, strlen(lastSlash) - 1);
00721 
00722         strncat(msg, "\0", 1);
00723     }
00724 
00725     gtk_label_set_text(GTK_LABEL(sMinorLabel), msg);
00726     gtk_widget_draw(sMinorLabel, NULL);
00727 
00728     XI_GTK_UPDATE_UI();
00729 }
00730 
00731 void
00732 nsInstallDlg::MajorProgressCB(char *aName, int aNum, int aTotal, int aActivity)
00733 {
00734     // DUMP("MajorProgressCB");
00735 
00736     char msg[256];
00737 
00738     if (!aName)
00739        return;
00740 
00741 #ifdef DEBUG
00742     printf("%s %d: Name = %s\tNum = %d\tTotal = %d\tAct = %d\n", 
00743     __FILE__, __LINE__, aName, aNum, aTotal, aActivity);
00744 #endif
00745 
00746     switch (aActivity)
00747     {
00748         case ACT_DOWNLOAD:
00749             if (!bDownload)
00750                 sprintf(msg, gCtx->Res("PREPARING"), aName);
00751             break;
00752 
00753         case ACT_EXTRACT:
00754             sprintf(msg, gCtx->Res("EXTRACTING"), aName);
00755             break;
00756 
00757         case ACT_INSTALL:
00758             sprintf(msg, gCtx->Res("INSTALLING_XPI"), aName);
00759             break;
00760 
00761         default:
00762             break;
00763     }
00764 
00765     gtk_label_set_text(GTK_LABEL(sMajorLabel), msg);
00766     gtk_widget_show(sMajorLabel);
00767 
00768     if (aTotal <= 0)
00769     {
00770         XI_ASSERT(0, "aTotal was <= 0");
00771         XI_GTK_UPDATE_UI();
00772         return;
00773     }
00774 
00775     gfloat percent = (gfloat)((gfloat)aNum/(gfloat)aTotal);
00776     gtk_progress_bar_update(GTK_PROGRESS_BAR(sMajorProgBar), percent);
00777     gtk_widget_show(sMajorProgBar);
00778 
00779     // reset minor progress ui
00780     if (aActivity == ACT_INSTALL)
00781     {
00782         gtk_label_set_text(GTK_LABEL(sMinorLabel), "");
00783         gtk_progress_bar_update(GTK_PROGRESS_BAR(sMinorProgBar), (gfloat)0);
00784         gtk_widget_show(sMinorLabel);
00785         gtk_widget_show(sMinorProgBar);
00786     }
00787 
00788     XI_GTK_UPDATE_UI();
00789 }
00790 
00791 const int kCharsInDLLabel = 50;
00792 
00793 void
00794 nsInstallDlg::SetDownloadComp(nsComponent *aComp, int aURLIndex, 
00795                               int aNum, int aTotal)
00796 {
00797     static char xpiDir[MAXPATHLEN];
00798     static int bHaveXPIDir = FALSE;
00799     char label[MAXPATHLEN];
00800     char localPath[MAXPATHLEN];
00801     
00802     if (!aComp)
00803        return;
00804 
00805     if (!bHaveXPIDir)
00806     {
00807         getcwd(xpiDir, MAXPATHLEN);
00808         strcat(xpiDir, "/xpi");
00809         bHaveXPIDir = TRUE;
00810     }
00811 
00812     // update comp name 
00813     sprintf(label, "%s [%d/%d]", aComp->GetDescShort(), aNum, aTotal);
00814     gtk_label_set_text(GTK_LABEL(sDLProgress.compName), label);
00815 
00816     // update from URL 
00817     label[0] = 0;
00818     CompressToFit(aComp->GetURL(aURLIndex), label, kCharsInDLLabel);
00819     gtk_label_set_text(GTK_LABEL(sDLProgress.URL), label);
00820 
00821     // to local path 
00822     label[0] = 0;
00823     sprintf(localPath, "%s/%s", xpiDir, aComp->GetArchive());
00824     CompressToFit(localPath, label, kCharsInDLLabel);
00825     gtk_label_set_text(GTK_LABEL(sDLProgress.localPath), label);
00826     
00827     gettimeofday(&sDLStartTime, NULL);
00828 }
00829 
00830 #define SHOW_EVERY_N_KB 16
00831 int
00832 nsInstallDlg::DownloadCB(int aBytesRd, int aTotal)
00833 {
00834     struct timeval now;
00835     char label[64];
00836     int rate;
00837     gfloat percent = 0;
00838     static int timesCalled = 0;
00839     static int activityCount = 0;
00840     int dlKB;
00841     static int lastTotal = 0;
00842     static int lastBytesRd = 0;
00843 
00844     // new component being downloaded
00845     if (lastTotal != aTotal)
00846     {
00847         lastBytesRd = 0; // reset
00848         lastTotal = aTotal;
00849     }
00850     
00851     if ((aBytesRd - lastBytesRd) > 0)
00852     {
00853         sDLProgress.downloadedBytes += aBytesRd - lastBytesRd;
00854         lastBytesRd = aBytesRd;
00855     }
00856 
00857     if (bDLPause || bDLCancel)
00858     {
00859         return nsHTTPConn::E_USER_CANCEL;
00860     }
00861 
00862     if (++timesCalled < SHOW_EVERY_N_KB)
00863         return 0; 
00864     else
00865         timesCalled = 0;
00866 
00867     gettimeofday(&now, NULL);
00868     rate = (int) nsSocket::CalcRate(&sDLStartTime, &now, aBytesRd);
00869 
00870     // update the status -- bytes thus far, rate, percent in prog bar
00871     dlKB = sDLProgress.downloadedBytes/1024;
00872     sprintf(label, gCtx->Res("DL_STATUS_STR"), dlKB, sDLProgress.totalKB, rate);
00873     gtk_label_set_text(GTK_LABEL(sDLProgress.status), label);
00874 
00875 /*
00876     // only update rate in major label line
00877     XXX remove this: DLRATE no longer exists
00878     sprintf(label, gCtx->Res("DLRATE"), rate);
00879     gtk_label_set_text(GTK_LABEL(sRateLabel), label);
00880 */
00881 
00882     if (sDLProgress.totalKB <= 0) 
00883     {
00884         // show some activity
00885         if (activityCount >= 5) activityCount = 0;
00886         percent = (gfloat)( (gfloat)activityCount++/ (gfloat)5 ); 
00887         gtk_progress_set_activity_mode(GTK_PROGRESS(sDLProgress.progBar), TRUE);
00888         gtk_progress_bar_update(GTK_PROGRESS_BAR(sDLProgress.progBar), percent);
00889     }
00890     else
00891     {
00892         percent = (gfloat)dlKB/(gfloat)sDLProgress.totalKB;
00893 #ifdef DEBUG
00894     printf("DLProgress: %d of %d (%f percent) at %d KB/sec\n", dlKB,
00895             sDLProgress.totalKB, percent, rate);
00896 #endif
00897         gtk_progress_set_activity_mode(GTK_PROGRESS(sDLProgress.progBar), 
00898             FALSE); 
00899         gtk_progress_bar_update(GTK_PROGRESS_BAR(sDLProgress.progBar), percent);
00900     }
00901 
00902     XI_GTK_UPDATE_UI();
00903     return 0;
00904 }
00905 
00906 void
00907 nsInstallDlg::ClearRateLabel()
00908 {
00909     gtk_label_set_text(GTK_LABEL(sRateLabel), "");
00910     gtk_progress_set_activity_mode(GTK_PROGRESS(sMajorProgBar), FALSE); 
00911     XI_GTK_UPDATE_UI();
00912 }
00913 
00914 void
00915 nsInstallDlg::SaveModulesToggled(GtkWidget *aWidget, gpointer aData)
00916 {
00917     if (GTK_TOGGLE_BUTTON(aWidget)->active)
00918     {
00919         DUMP("Save modules toggled on");
00920         gCtx->opt->mSaveModules = TRUE;
00921     }
00922     else
00923     {
00924         DUMP("Save modules toggled off");
00925         gCtx->opt->mSaveModules = FALSE;
00926     }
00927 }
00928 
00929 void
00930 nsInstallDlg::ShowProxySettings(GtkWidget *aWidget, gpointer aData)
00931 {
00932     GtkWidget *psDlg, *psTable;
00933     GtkWidget *okButton, *cancelButton;
00934     GtkWidget *psLabel[NUM_PS_ENTRIES];
00935     int i;
00936     char resName[16], *text = nsnull;
00937 
00938     psDlg = gtk_dialog_new();
00939     gtk_window_set_title(GTK_WINDOW(psDlg), gCtx->opt->mTitle);
00940     gtk_window_set_position(GTK_WINDOW(psDlg), GTK_WIN_POS_CENTER);
00941 
00942     psTable = gtk_table_new(5, 2, FALSE);
00943     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(psDlg)->vbox), psTable);
00944     gtk_widget_show(psTable);
00945 
00946     // create labels
00947     for (i = 0; i < NUM_PS_ENTRIES; ++i) 
00948     {
00949         sprintf(resName, "PS_LABEL%d", i);
00950         psLabel[i] = gtk_label_new(gCtx->Res(resName));
00951         gtk_widget_show(psLabel[i]);
00952 
00953         gtk_table_attach_defaults(GTK_TABLE(psTable), psLabel[i],
00954                                   0, 1, i, i + 1);
00955     }
00956     
00957     // create text entry fields
00958     for (i = 0; i < NUM_PS_ENTRIES; ++i)
00959     {
00960         sPSTextEntry[i] = gtk_entry_new();
00961         gtk_entry_set_editable(GTK_ENTRY(sPSTextEntry[i]), TRUE);
00962 
00963         // reset text if we already opened this dlg before
00964         if (i == 0) text = gCtx->opt->mProxyHost;
00965         if (i == 1) text = gCtx->opt->mProxyPort;
00966         if (i == 2) text = gCtx->opt->mProxyUser;
00967         if (i == 3) text = gCtx->opt->mProxyPswd;
00968 
00969         if (text)
00970             gtk_entry_set_text(GTK_ENTRY(sPSTextEntry[i]), text);
00971 
00972         // password field
00973         if (i + 1 == NUM_PS_ENTRIES)
00974             gtk_entry_set_visibility(GTK_ENTRY(sPSTextEntry[i]), FALSE); 
00975 
00976         gtk_widget_show(sPSTextEntry[i]);
00977 
00978         gtk_table_attach(GTK_TABLE(psTable), sPSTextEntry[i], 
00979             1, 2, i, i + 1,
00980             static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00981             static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND), 5, 5);
00982     }
00983 
00984     // pre-populate text entry fields if data already stored
00985     okButton = gtk_button_new_with_label(gCtx->Res("OK_LABEL"));
00986     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(psDlg)->action_area),
00987         okButton);
00988     gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
00989                    GTK_SIGNAL_FUNC(PSDlgOK), psDlg);
00990     gtk_widget_show(okButton);
00991 
00992     cancelButton = gtk_button_new_with_label(gCtx->Res("CANCEL_LABEL"));
00993     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(psDlg)->action_area),
00994         cancelButton);
00995     gtk_signal_connect(GTK_OBJECT(cancelButton), "clicked",
00996                    GTK_SIGNAL_FUNC(PSDlgCancel), psDlg);
00997     gtk_widget_show(cancelButton);
00998 
00999     gtk_widget_show(psDlg);
01000 }
01001 
01002 void
01003 nsInstallDlg::PSDlgOK(GtkWidget *aWidget, gpointer aData)
01004 {
01005     GtkWidget *dlg = (GtkWidget *) aData;
01006     char *text;
01007 
01008     // grab proxy host field
01009     if (sPSTextEntry[0])
01010     {
01011         text = gtk_editable_get_chars(GTK_EDITABLE(sPSTextEntry[0]), 0, -1);
01012         if (text)
01013         {
01014             XI_IF_FREE(gCtx->opt->mProxyHost);
01015             gCtx->opt->mProxyHost = text;
01016         }
01017     }
01018 
01019     // grab proxy port field
01020     if (sPSTextEntry[1])
01021     {
01022         text = gtk_editable_get_chars(GTK_EDITABLE(sPSTextEntry[1]), 0, -1);
01023         if (text)
01024         {
01025             XI_IF_FREE(gCtx->opt->mProxyPort);
01026             gCtx->opt->mProxyPort = text;
01027         }
01028     }
01029 
01030     // grab proxy user field
01031     if (sPSTextEntry[2])
01032     {
01033         text = gtk_editable_get_chars(GTK_EDITABLE(sPSTextEntry[2]), 0, -1);
01034         if (text)
01035         {
01036             XI_IF_FREE(gCtx->opt->mProxyUser);
01037             gCtx->opt->mProxyUser = text;
01038         }
01039     }
01040 
01041     // grab proxy pswd field
01042     if (sPSTextEntry[3])
01043     {
01044         text = gtk_editable_get_chars(GTK_EDITABLE(sPSTextEntry[3]), 0, -1);
01045         if (text)
01046         {
01047             XI_IF_FREE(gCtx->opt->mProxyPswd);
01048             gCtx->opt->mProxyPswd = text;
01049         }
01050     }
01051 
01052     if (dlg)
01053         gtk_widget_destroy(dlg);
01054 }
01055 
01056 void
01057 nsInstallDlg::PSDlgCancel(GtkWidget *aWidget, gpointer aData)
01058 {
01059     GtkWidget *dlg = (GtkWidget *) aData;
01060 
01061     if (dlg)
01062         gtk_widget_destroy(dlg);
01063 }
01064 
01065 void
01066 nsInstallDlg::DLPause(GtkWidget *aWidget, gpointer aData)
01067 {
01068     DUMP("DLPause");
01069 
01070     // set pause for download callback to return to libxpnet
01071     bDLPause = TRUE;
01072 
01073     // disbale pause button
01074     gtk_widget_set_sensitive(gCtx->back, FALSE);
01075 
01076     // enable resume button
01077     gtk_widget_set_sensitive(gCtx->next, TRUE);
01078 
01079     gtk_main();
01080 }
01081 
01082 void
01083 nsInstallDlg::DLResume(GtkWidget *aWidget, gpointer aData)
01084 {
01085     DUMP("DLResume");
01086 
01087     if (!bDLPause)
01088     {
01089         DUMP("Not paused");
01090         return;
01091     }
01092 
01093     DUMP("Unsetting bDLPause");
01094     bDLPause = FALSE;
01095 
01096     // disable resume button
01097     gtk_widget_set_sensitive(gCtx->next, FALSE);
01098 
01099     // enable pause button
01100     gtk_widget_set_sensitive(gCtx->back, TRUE);
01101 
01102     gtk_main_quit();
01103 
01104     PerformInstall();
01105  
01106     return;
01107 }
01108 
01109 void
01110 nsInstallDlg::DLCancel(GtkWidget *aWidget, gpointer aData)
01111 {
01112     DUMP("DLCancel");
01113 
01114     // show cancellation confirm dialog
01115     // XXX    TO DO
01116 
01117     // set cancel for download callback to return to libxpnet
01118     bDLCancel = TRUE;
01119 
01120 #ifdef DEBUG
01121     printf("%s %d: bDLPause: %d\tbDLCancel: %d\n", __FILE__, __LINE__, 
01122                    bDLPause, bDLCancel);
01123 #endif
01124 
01125     // already paused then take explicit action to quit
01126     if (bDLPause)
01127     {
01128          gtk_main_quit();
01129     }
01130 }
01131 
01132 int
01133 nsInstallDlg::CancelOrPause()
01134 {
01135     int err = OK;
01136 
01137     if (bDLPause)
01138     {
01139         err = E_DL_PAUSE;
01140     }
01141     else if (bDLCancel)
01142     {
01143         err = E_DL_CANCEL;
01144     }
01145     
01146     return err;
01147 }
01148 
01149 static GtkWidget *crcDlg = (GtkWidget *) NULL;
01150 
01151 void
01152 nsInstallDlg::ShowCRCDlg()
01153 {
01154     GtkWidget *label;
01155 
01156     if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT) {
01157        ErrorHandler(E_CRC_FAILED);
01158        return;
01159     }
01160 
01161     if ( crcDlg == (GtkWidget *) NULL ) {
01162        // throw up dialog informing user to press resume
01163        // or to cancel out
01164       crcDlg = gtk_dialog_new_with_buttons(gCtx->opt->mTitle, NULL,
01165                                            (GtkDialogFlags) 0,
01166                                            GTK_STOCK_OK,
01167                                            GTK_RESPONSE_NONE,
01168                                            NULL);
01169 
01170       label = gtk_label_new(gCtx->Res("CRC_CHECK"));
01171 
01172       g_signal_connect_swapped(GTK_OBJECT(crcDlg), "response",
01173                                G_CALLBACK(CRCOKCb), GTK_OBJECT(crcDlg));
01174 
01175       gtk_container_add(GTK_CONTAINER(GTK_DIALOG(crcDlg)->vbox), label);
01176       gtk_widget_show_all(crcDlg);
01177     }
01178     XI_GTK_UPDATE_UI();
01179 }
01180 
01181 int
01182 nsInstallDlg::ShowCRCFailedDlg()
01183 {
01184     GtkWidget *crcFailedDlg, *label;
01185 
01186     // throw up dialog informing user to press resume
01187     // or to cancel out
01188     if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT) {
01189        ErrorHandler(E_CRC_FAILED);
01190        return OK;
01191     }
01192 
01193     crcFailedDlg = gtk_dialog_new_with_buttons(gCtx->opt->mTitle, NULL,
01194                                                GTK_DIALOG_MODAL,
01195                                                GTK_STOCK_OK,
01196                                                GTK_RESPONSE_NONE,
01197                                                NULL);
01198     label = gtk_label_new(gCtx->Res("CRC_FAILED"));
01199 
01200     g_signal_connect_swapped(GTK_OBJECT(crcFailedDlg), "response",
01201                              G_CALLBACK(CRCFailedOK), GTK_OBJECT(crcFailedDlg));
01202     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(crcFailedDlg)->vbox), label);
01203     gtk_widget_show_all(crcFailedDlg);
01204     XI_GTK_UPDATE_UI();
01205 
01206     return OK;
01207 }
01208 
01209 int
01210 nsInstallDlg::ShowCxnDroppedDlg()
01211 {
01212     GtkWidget *cxnDroppedDlg, *label;
01213 
01214     // throw up dialog informing user to press resume
01215     // or to cancel out
01216     if (gCtx->opt->mMode == nsXIOptions::MODE_SILENT) {
01217        ErrorHandler(E_NO_DOWNLOAD);
01218        return OK;
01219     }
01220 
01221     cxnDroppedDlg = gtk_dialog_new_with_buttons(gCtx->opt->mTitle, NULL,
01222                                                 GTK_DIALOG_MODAL,
01223                                                 GTK_STOCK_OK,
01224                                                 GTK_RESPONSE_NONE,
01225                                                 NULL);
01226 
01227     label = gtk_label_new(gCtx->Res("CXN_DROPPED"));
01228     g_signal_connect_swapped(GTK_OBJECT(cxnDroppedDlg), "response",
01229                              G_CALLBACK(CxnDroppedOK), GTK_OBJECT(cxnDroppedDlg));
01230     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(cxnDroppedDlg)->vbox), label);
01231     gtk_widget_show_all(cxnDroppedDlg);
01232     XI_GTK_UPDATE_UI();
01233 
01234     return OK;
01235 }
01236 
01237 void
01238 nsInstallDlg::CRCFailedOK(GtkWidget *aWidget, gpointer aData)
01239 {
01240   gtk_main_quit();
01241   return;
01242 }
01243 
01244 void
01245 nsInstallDlg::DestroyCRCDlg()
01246 {
01247   CRCOKCb( (GtkWidget *) NULL, (gpointer) NULL );
01248 }
01249 
01250 void
01251 nsInstallDlg::CRCOKCb(GtkWidget *aWidget, gpointer aData)
01252 {
01253     if (crcDlg != (GtkWidget *) NULL)
01254         gtk_widget_destroy(crcDlg);
01255     crcDlg = (GtkWidget *) NULL;
01256 
01257     return;
01258 }
01259 
01260 void
01261 nsInstallDlg::CxnDroppedOK(GtkWidget *aWidget, gpointer aData)
01262 {
01263     GtkWidget *cxnDroppedDlg = (GtkWidget *) aData;
01264     
01265     if (cxnDroppedDlg)
01266         gtk_widget_destroy(cxnDroppedDlg);
01267 
01268     return;
01269 }
01270 
01271 void
01272 nsInstallDlg::HideNavButtons()
01273 {
01274     gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
01275     gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
01276     gtk_signal_disconnect(GTK_OBJECT(gCtx->cancel), gCtx->cancelID);
01277 
01278     gtk_widget_set_sensitive(gCtx->back, FALSE);
01279     gtk_widget_set_sensitive(gCtx->next, FALSE);
01280     gtk_widget_set_sensitive(gCtx->cancel, FALSE);
01281 }
01282 
01283 void
01284 nsInstallDlg::InitDLProgress( int isFirst )
01285 {
01286     GtkWidget *titles[4];
01287     GtkWidget *hbox;
01288     GtkWidget *table;
01289 
01290     gCtx->idlg->HideTable();
01291 
01292     if ( isFirst == TRUE ) {
01293             sDLProgress.vbox = gtk_vbox_new(FALSE, 10);
01294             gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), 
01295                 sDLProgress.vbox, NULL);
01296             gtk_widget_show(sDLProgress.vbox);
01297                     
01298             table = gtk_table_new(5, 2, FALSE);
01299             gtk_box_pack_start(GTK_BOX(sDLProgress.vbox), table, FALSE, 
01300                 FALSE, 0);
01301             gtk_widget_show(table);
01302 
01303             // setup static title progress labels in table left column
01304             titles[0] = gtk_label_new(gCtx->Res("DOWNLOADING"));
01305             titles[1] = gtk_label_new(gCtx->Res("FROM"));
01306             titles[2] = gtk_label_new(gCtx->Res("TO"));
01307             titles[3] = gtk_label_new(gCtx->Res("STATUS"));
01308 
01309             // setup dynamic progress labels in right column
01310             sDLProgress.compName = gtk_label_new(gCtx->Res("UNKNOWN"));
01311             sDLProgress.URL = gtk_label_new(gCtx->Res("UNKNOWN"));
01312             sDLProgress.localPath = gtk_label_new(gCtx->Res("UNKNOWN"));
01313             sDLProgress.status = gtk_label_new(gCtx->Res("UNKNOWN"));
01314 
01315             // pack and show titles
01316             for (int i = 0; i < 4; ++i)
01317             {
01318                 hbox = gtk_hbox_new(FALSE, 10);
01319                 gtk_box_pack_end(GTK_BOX(hbox), titles[i], FALSE, FALSE, 0);
01320                 gtk_table_attach(GTK_TABLE(table), hbox, 
01321                     0, 1, i, i + 1, GTK_FILL, GTK_FILL, 5, 5);
01322                 gtk_widget_show(titles[i]);
01323                 gtk_widget_show(hbox);
01324             }
01325 
01326             // pack and show dynamic labels 
01327             hbox = gtk_hbox_new(FALSE, 10);
01328             gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.compName, FALSE, FALSE, 0);
01329             gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 0, 1,
01330                 GTK_FILL, GTK_FILL, 5, 5);
01331             gtk_widget_show(sDLProgress.compName);
01332             gtk_widget_show(hbox);
01333 
01334             hbox = gtk_hbox_new(FALSE, 10);
01335             gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.URL, FALSE, FALSE, 0);
01336             gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2,
01337                 GTK_FILL, GTK_FILL, 5, 5);
01338             gtk_widget_show(sDLProgress.URL);
01339             gtk_widget_show(hbox);
01340 
01341             hbox = gtk_hbox_new(FALSE, 10);
01342             gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.localPath, FALSE, 
01343                 FALSE, 0);
01344             gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 2, 3,
01345                 GTK_FILL, GTK_FILL, 5, 5);
01346             gtk_widget_show(sDLProgress.localPath);
01347             gtk_widget_show(hbox);
01348 
01349             hbox = gtk_hbox_new(FALSE, 10);
01350             gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.status, FALSE, 
01351                 FALSE, 0);
01352             gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 3, 4,
01353                 GTK_FILL, GTK_FILL, 5, 5);
01354             gtk_widget_show(sDLProgress.status);
01355             gtk_widget_show(hbox);
01356 
01357             // init and show prog bar
01358             sDLProgress.progBar = gtk_progress_bar_new();
01359 
01360             // show prog bar
01361             hbox = gtk_hbox_new(TRUE, 10);
01362             gtk_box_pack_start(GTK_BOX(hbox), sDLProgress.progBar, FALSE, 
01363               TRUE, 0);
01364             gtk_box_pack_start(GTK_BOX(sDLProgress.vbox), hbox, FALSE, 
01365               FALSE, 0);
01366             gtk_widget_show(sDLProgress.progBar);
01367             gtk_widget_show(hbox);
01368     }
01369 
01370     // set to non-activity mode and initialize 
01371     gtk_progress_set_activity_mode(GTK_PROGRESS(sDLProgress.progBar), FALSE);
01372     gtk_progress_bar_update(GTK_PROGRESS_BAR(sDLProgress.progBar), (gfloat) 0);
01373 
01374     // compute total download size
01375     sDLProgress.downloadedBytes = 0;
01376     sDLProgress.totalKB = TotalDLSize();
01377 
01378     XI_GTK_UPDATE_UI();
01379 }
01380 
01381 void
01382 nsInstallDlg::InitInstallProgress()
01383 {
01384     if ( sDLProgress.vbox )
01385             gtk_widget_hide(sDLProgress.vbox);
01386     gCtx->idlg->ShowTable();
01387 }
01388 
01389 int
01390 nsInstallDlg::TotalDLSize()
01391 {
01392     int total = 0; // in KB
01393     int bCustom;
01394     nsComponentList *comps;
01395     nsComponent *currComp;
01396     int archiveSize, currentSize;
01397 
01398     bCustom = (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1));
01399     comps = gCtx->sdlg->GetSelectedSetupType()->GetComponents();
01400     currComp = comps->GetHead();
01401     
01402     // loop through all components
01403     while (currComp)
01404     {
01405         if ((bCustom && currComp->IsSelected()) || (!bCustom))
01406         {
01407             // if still have to download 
01408             if (!currComp->IsDownloaded())
01409             {
01410                 // find archive size - amount downloaded already
01411                 archiveSize = currComp->GetArchiveSize();
01412                 currentSize = currComp->GetCurrentSize();
01413 
01414 #ifdef DEBUG
01415                 printf("%s ar sz = %d cu sz = %d\n", currComp->GetArchive(), 
01416                         archiveSize, currentSize);
01417 #endif
01418 
01419                 total += (archiveSize - currentSize);
01420             }
01421         }
01422         currComp = currComp->GetNext();
01423     }
01424 
01425     return total;
01426 }
01427 
01428 void
01429 nsInstallDlg::CompressToFit(char *aOrigStr, char *aOutStr, int aOutStrLen)
01430 {
01431     int origStrLen;
01432     int halfOutStrLen;
01433     char *lastPart; // last aOrigStr part start
01434 
01435     if (!aOrigStr || !aOutStr || aOutStrLen <= 0)
01436         return;
01437 
01438     origStrLen = strlen(aOrigStr);
01439     halfOutStrLen = (aOutStrLen/2) - 2; // minus 2 since ellipsis is 3 chars
01440     lastPart = aOrigStr + origStrLen - halfOutStrLen;
01441 
01442     strncpy(aOutStr, aOrigStr, halfOutStrLen);
01443     *(aOutStr + halfOutStrLen) = 0;
01444     strcat(aOutStr, "...");
01445     strncat(aOutStr, lastPart, strlen(lastPart));
01446     *(aOutStr + aOutStrLen + 1) = 0;
01447 }
01448 
01449 void
01450 nsInstallDlg::ReInitUI( void )
01451 {
01452   InitDLProgress( FALSE );
01453 }