Back to index

lightning-sunbird  0.9+nobinonly
nsComponentsDlg.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 of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or 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 "nsComponentsDlg.h"
00041 #include "nsXInstaller.h"
00042 #include "check_on.xpm"
00043 #include "check_off.xpm"
00044 #include <gdk/gdkkeysyms.h>
00045 
00046 static nsSetupType     *sCustomST; // cache a pointer to the custom setup type
00047 static GtkWidget       *sDescLong;
00048 static gint             sCurrRowSelected;
00049 
00050 nsComponentsDlg::nsComponentsDlg() :
00051     mMsg0(NULL),
00052     mCompList(NULL)
00053 {
00054 }
00055 
00056 nsComponentsDlg::~nsComponentsDlg()
00057 {
00058     XI_IF_FREE(mMsg0);
00059     XI_IF_DELETE(mCompList);
00060 }
00061 
00062 void
00063 nsComponentsDlg::Back(GtkWidget *aWidget, gpointer aData)
00064 {
00065     DUMP("Back");
00066     if (aData != gCtx->cdlg) return;
00067 #ifdef MOZ_WIDGET_GTK
00068     if (gCtx->bMoving)
00069     {
00070         gCtx->bMoving = FALSE;
00071         return;
00072     }
00073 #endif
00074 
00075     // hide this notebook page
00076     gCtx->cdlg->Hide();
00077 
00078     gCtx->sdlg->Show();
00079 
00080     // don't set bMoving since setuptype has no "back"
00081 }
00082 
00083 void
00084 nsComponentsDlg::Next(GtkWidget *aWidget, gpointer aData)
00085 {
00086     DUMP("Next");
00087     if (aData != gCtx->cdlg) return;
00088 #ifdef MOZ_WIDGET_GTK
00089     if (gCtx->bMoving)
00090     {
00091         gCtx->bMoving = FALSE;
00092         return;
00093     }
00094 #endif
00095 
00096     if (OK != nsSetupTypeDlg::VerifyDiskSpace())
00097         return;
00098 
00099     // hide this notebook page
00100     gCtx->cdlg->Hide();
00101 
00102     // show the next dlg
00103     gCtx->idlg->Show();
00104 #ifdef MOZ_WIDGET_GTK
00105     gCtx->bMoving = TRUE;
00106 #endif
00107 }
00108 
00109 int
00110 nsComponentsDlg::Parse(nsINIParser *aParser)
00111 {
00112     int err = OK;
00113     char *showDlg = NULL;
00114     int bufsize = 0;
00115     int i, j, compListLen = 0;
00116 
00117     char *currSec = (char *) malloc(strlen(COMPONENT) + 3);
00118     if (!currSec) return E_MEM;
00119     char *currDescShort = NULL;
00120     char *currDescLong = NULL;
00121     char *currArchive = NULL;
00122     char *currInstallSizeStr = NULL;
00123     char *currArchiveSizeStr = NULL;
00124     char *currAttrStr = NULL;
00125     char *currURL = NULL;
00126     char *currDepName = NULL;
00127     char urlKey[MAX_URL_LEN];
00128     char dependeeKey[MAX_DEPENDEE_KEY_LEN];
00129     nsComponent *currComp = NULL;
00130     nsComponent *currDepComp = NULL;
00131     nsComponent *currIdxComp = NULL; 
00132     XI_VERIFY(gCtx);
00133 
00134     /* optional keys */
00135     err = aParser->GetStringAlloc(DLG_COMPONENTS, MSG0, &mMsg0, &bufsize);
00136     if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00137 
00138     bufsize = 0;
00139     err = aParser->GetStringAlloc(DLG_COMPONENTS, TITLE, &mTitle, &bufsize);
00140     if (err != OK  && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00141     if (bufsize == 0)
00142             XI_IF_FREE(mTitle); 
00143 
00144     mCompList = new nsComponentList();
00145      
00146     for (i=0; i<MAX_COMPONENTS; i++)
00147     {
00148         currDescShort = NULL;
00149         currDescLong = NULL;
00150         currArchive = NULL;
00151         currInstallSizeStr = NULL;
00152         currArchiveSizeStr = NULL;
00153         currAttrStr = NULL;
00154 
00155         sprintf(currSec, COMPONENTd, i);
00156 
00157         err = aParser->GetStringAlloc(currSec, DESC_SHORT, 
00158                                             &currDescShort, &bufsize);
00159         if (err != OK && err != nsINIParser::E_NO_SEC) goto BAIL; 
00160         if (bufsize == 0 || err == nsINIParser::E_NO_SEC)
00161         {
00162             err = OK;
00163             break;
00164         }
00165 
00166         XI_ERR_BAIL(aParser->GetStringAlloc(currSec, DESC_LONG,
00167                                             &currDescLong, &bufsize));
00168         XI_ERR_BAIL(aParser->GetStringAlloc(currSec, ARCHIVE,
00169                                             &currArchive, &bufsize));
00170         XI_ERR_BAIL(aParser->GetStringAlloc(currSec, INSTALL_SIZE,  
00171                                             &currInstallSizeStr, &bufsize));
00172         XI_ERR_BAIL(aParser->GetStringAlloc(currSec, ARCHIVE_SIZE,  
00173                                             &currArchiveSizeStr, &bufsize));
00174         err = aParser->GetStringAlloc(currSec, ATTRIBUTES,
00175                                       &currAttrStr, &bufsize);
00176         if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
00177 
00178         currComp = new nsComponent();
00179         if (!currComp) return E_MEM;
00180 
00181         currComp->SetIndex(i);
00182         currComp->SetDescShort(currDescShort);
00183         currComp->SetDescLong(currDescLong);
00184         currComp->SetArchive(currArchive);
00185         currComp->SetInstallSize(atoi(currInstallSizeStr));
00186         currComp->SetArchiveSize(atoi(currArchiveSizeStr));
00187         if (NULL != strstr(currAttrStr, SELECTED_ATTR))
00188         { 
00189             currComp->SetSelected();
00190             currComp->DepAddRef();
00191         }
00192         else
00193             currComp->SetUnselected();
00194         if (NULL != strstr(currAttrStr, INVISIBLE_ATTR))
00195             currComp->SetInvisible();
00196         else
00197             currComp->SetVisible();
00198         if (NULL != strstr(currAttrStr, LAUNCHAPP_ATTR))
00199             currComp->SetLaunchApp();
00200         else
00201             currComp->SetDontLaunchApp();
00202         if (NULL != strstr(currAttrStr, DOWNLOAD_ONLY_ATTR))
00203             currComp->SetDownloadOnly();
00204 
00205         // parse failover URLs
00206         for (j = 0; j < MAX_URLS; j++)
00207         {
00208             sprintf(urlKey, URLd, j);
00209             bufsize = 0;
00210             err = aParser->GetStringAlloc(currSec, urlKey, &currURL, &bufsize);
00211             if (err == nsINIParser::E_NO_KEY || bufsize == 0)  // paranoia!
00212                 break;
00213             if (err != OK) goto BAIL; else err = OK;
00214             currComp->SetURL(currURL, j);
00215         }
00216 
00217         XI_ERR_BAIL(mCompList->AddComponent(currComp));
00218     }
00219 
00220     compListLen = mCompList->GetLength();
00221     if (0 == compListLen)
00222     {
00223         XI_IF_DELETE(mCompList);
00224         err = E_NO_COMPONENTS;
00225         goto BAIL;
00226     }
00227 
00228     // now parse dependee list for all components
00229     for (i = 0; i < compListLen; i++)
00230     {
00231         memset(currSec, 0, strlen(COMPONENT) + 3);
00232         sprintf(currSec, COMPONENTd, i);
00233 
00234         currIdxComp = mCompList->GetCompByIndex(i);
00235         if (!currIdxComp)
00236             continue;
00237 
00238         for (j = 0; j < MAX_COMPONENTS; j++)
00239         {
00240             currDepComp = NULL;
00241             memset(dependeeKey, 0, MAX_DEPENDEE_KEY_LEN);
00242             sprintf(dependeeKey, DEPENDEEd, j);
00243 
00244             err = aParser->GetStringAlloc(currSec, dependeeKey, 
00245                 &currDepName, &bufsize);
00246             if (bufsize == 0 || err != nsINIParser::OK || !currDepName) 
00247             {
00248                 err = OK;
00249                 break; // no more dependees
00250             }
00251             
00252             currDepComp = mCompList->GetCompByShortDesc(currDepName);
00253             if (!currDepComp) // unexpected dependee name
00254                 continue;
00255 
00256             currIdxComp->AddDependee(currDepName);
00257         }
00258     }
00259 
00260 BAIL:
00261     XI_IF_FREE(currSec);
00262 
00263     return err;
00264 }
00265 
00266 int
00267 nsComponentsDlg::Show()
00268 {
00269     int err = OK;
00270     int customSTIndex = 0, i;
00271     int numRows = 0;
00272     int currRow = 0;
00273     GtkWidget *hbox = NULL;
00274 
00275     XI_VERIFY(gCtx);
00276     XI_VERIFY(gCtx->notebook);
00277 
00278     if (mWidgetsInit == FALSE)
00279     {
00280         customSTIndex = gCtx->sdlg->GetNumSetupTypes();
00281         sCustomST = gCtx->sdlg->GetSetupTypeList();
00282         for (i=1; i<customSTIndex; i++)
00283             sCustomST = sCustomST->GetNext();
00284         DUMP(sCustomST->GetDescShort());
00285 
00286         // create a new table and add it as a page of the notebook
00287         mTable = gtk_table_new(5, 1, FALSE);
00288         gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), mTable, NULL);
00289         mPageNum = gtk_notebook_get_current_page(GTK_NOTEBOOK(gCtx->notebook));
00290         gtk_widget_show(mTable);
00291 
00292         // 1st row: a label (msg0)
00293         // insert a static text widget in the first row
00294         GtkWidget *msg0 = gtk_label_new(mMsg0);
00295         hbox = gtk_hbox_new(FALSE, 0);
00296         gtk_box_pack_start(GTK_BOX(hbox), msg0, FALSE, FALSE, 0);
00297         gtk_widget_show(hbox);
00298         gtk_table_attach(GTK_TABLE(mTable), hbox, 0, 1, 1, 2,
00299                          static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00300                                   GTK_FILL, 20, 20);
00301         gtk_widget_show(msg0);
00302 
00303         // 2nd row: a CList with a check box for each row (short desc)
00304         GtkWidget *list = NULL;
00305         GtkWidget *scrollwin = NULL;
00306         GtkStyle *style = NULL;
00307         GdkBitmap *ch_mask = NULL;
00308         GdkPixmap *checked = NULL;
00309         GdkBitmap *un_mask = NULL;
00310         GdkPixmap *unchecked = NULL;
00311         gchar *dummy[2] = { " ", " " };
00312         nsComponent *currComp = sCustomST->GetComponents()->GetHead();
00313         GtkWidget *descLongTable = NULL;
00314         GtkWidget *frame = NULL;
00315 
00316         scrollwin = gtk_scrolled_window_new(NULL, NULL);
00317         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
00318             GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
00319 
00320         list = gtk_clist_new(2);
00321         gtk_clist_set_selection_mode(GTK_CLIST(list), GTK_SELECTION_BROWSE);
00322         gtk_clist_column_titles_hide(GTK_CLIST(list));
00323         gtk_clist_set_column_width(GTK_CLIST(list), 0, 20);
00324         gtk_clist_set_column_width(GTK_CLIST(list), 1, 200);
00325         gtk_clist_set_row_height(GTK_CLIST(list), 17);
00326         
00327         // determine number of rows we'll need
00328         numRows = sCustomST->GetComponents()->GetLengthVisible();
00329         for (i = 0; i < numRows; i++)
00330             gtk_clist_append(GTK_CLIST(list), dummy);
00331     
00332         style = gtk_widget_get_style(gCtx->window);
00333         checked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &ch_mask, 
00334                   &style->bg[GTK_STATE_NORMAL], (gchar **)check_on_xpm);
00335         unchecked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &un_mask,
00336                     &style->bg[GTK_STATE_NORMAL], (gchar **)check_off_xpm);
00337 
00338         while ((currRow < numRows) && currComp) // paranoia!
00339         {
00340             if (!currComp->IsInvisible())
00341             {
00342                 if (currComp->IsSelected()) 
00343                     gtk_clist_set_pixmap(GTK_CLIST(list), currRow, 0, 
00344                                          checked, ch_mask);
00345                 else
00346                     gtk_clist_set_pixmap(GTK_CLIST(list), currRow, 0, 
00347                                          unchecked, un_mask);
00348 
00349                 gtk_clist_set_text(GTK_CLIST(list), currRow, 1,
00350                                    currComp->GetDescShort());
00351                 currRow++;
00352             }
00353 
00354             currComp = sCustomST->GetComponents()->GetNext();
00355         }
00356 
00357         // by default, first row selected upon Show()
00358         sCurrRowSelected = 0; 
00359 
00360         gtk_signal_connect(GTK_OBJECT(list), "select_row",
00361                            GTK_SIGNAL_FUNC(RowSelected), NULL);
00362         gtk_signal_connect(GTK_OBJECT(list), "key_press_event",
00363                            GTK_SIGNAL_FUNC(KeyPressed), NULL);
00364         gtk_container_add(GTK_CONTAINER(scrollwin), list);
00365         gtk_widget_show(list);
00366         gtk_widget_show(scrollwin);
00367 
00368         hbox = gtk_hbox_new(FALSE, 0);
00369         gtk_box_pack_start(GTK_BOX(hbox), scrollwin, TRUE, TRUE, 0);
00370         gtk_widget_show(hbox);
00371         gtk_table_attach(GTK_TABLE(mTable), hbox, 0, 1, 2, 3,
00372             static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
00373                      static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
00374                       20, 0);
00375 
00376         // XXX     3rd row: labels for ds avail and ds reqd
00377 
00378         // 4th row: a frame with a label (long desc)
00379         descLongTable = gtk_table_new(1, 1, FALSE);
00380         gtk_widget_show(descLongTable);
00381 
00382         gtk_table_attach(GTK_TABLE(mTable), descLongTable, 0, 1, 4, 5,
00383             static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
00384             static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
00385                      20, 20);
00386         frame = gtk_frame_new(gCtx->Res("DESCRIPTION"));
00387         gtk_table_attach_defaults(GTK_TABLE(descLongTable), frame, 0, 1, 0, 1);
00388         gtk_widget_show(frame);
00389 
00390         sDescLong = gtk_label_new(
00391             sCustomST->GetComponents()->GetFirstVisible()->GetDescLong());
00392         hbox = gtk_hbox_new(FALSE, 0);
00393         gtk_box_pack_start(GTK_BOX(hbox), sDescLong, FALSE, FALSE, 20);
00394         gtk_widget_show(hbox);
00395 
00396         gtk_table_attach_defaults(GTK_TABLE(descLongTable), hbox, 0, 1, 0, 1);
00397         gtk_widget_show(sDescLong);
00398 
00399         mWidgetsInit = TRUE;
00400     }
00401     else
00402     {
00403         gtk_notebook_set_page(GTK_NOTEBOOK(gCtx->notebook), mPageNum);
00404         gtk_widget_show(mTable);
00405     }
00406 
00407     // signal connect the buttons
00408     gCtx->backID = gtk_signal_connect(GTK_OBJECT(gCtx->back), "clicked",
00409                    GTK_SIGNAL_FUNC(nsComponentsDlg::Back), gCtx->cdlg);
00410     gCtx->nextID = gtk_signal_connect(GTK_OBJECT(gCtx->next), "clicked",
00411                    GTK_SIGNAL_FUNC(nsComponentsDlg::Next), gCtx->cdlg);
00412 
00413     // show both back and next buttons
00414     gCtx->backLabel = gtk_label_new(gCtx->Res("BACK"));
00415     gCtx->nextLabel = gtk_label_new(gCtx->Res("NEXT"));
00416     gtk_container_add(GTK_CONTAINER(gCtx->back), gCtx->backLabel);
00417     gtk_container_add(GTK_CONTAINER(gCtx->next), gCtx->nextLabel);
00418     gtk_widget_show(gCtx->backLabel);
00419     gtk_widget_show(gCtx->nextLabel);
00420     gtk_widget_show(gCtx->back);
00421     gtk_widget_show(gCtx->next);
00422 
00423     GTK_WIDGET_SET_FLAGS(gCtx->next, GTK_CAN_DEFAULT);
00424     gtk_widget_grab_default(gCtx->next);
00425     gtk_widget_grab_focus(gCtx->next);
00426 
00427     return err;
00428 }
00429 
00430 int
00431 nsComponentsDlg::Hide()
00432 {
00433     gtk_widget_hide(mTable);
00434 
00435     // disconnect and remove this dlg's nav btns
00436     gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
00437     gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
00438 
00439     gtk_container_remove(GTK_CONTAINER(gCtx->back), gCtx->backLabel); 
00440     gtk_container_remove(GTK_CONTAINER(gCtx->next), gCtx->nextLabel); 
00441 
00442     gtk_widget_hide(gCtx->back);
00443     gtk_widget_hide(gCtx->next);
00444 
00445     return OK;
00446 }
00447 
00448 int
00449 nsComponentsDlg::SetMsg0(char *aMsg)
00450 {
00451     if (!aMsg)
00452         return E_PARAM;
00453 
00454     mMsg0 = aMsg;
00455     
00456     return OK;
00457 }
00458 
00459 char *
00460 nsComponentsDlg::GetMsg0()
00461 {
00462     if (mMsg0)
00463         return mMsg0;
00464 
00465     return NULL;
00466 }
00467 
00468 int
00469 nsComponentsDlg::SetCompList(nsComponentList *aCompList)
00470 {
00471     if (!aCompList)
00472         return E_PARAM;
00473 
00474     mCompList = aCompList;
00475 
00476     return OK;
00477 }
00478 
00479 nsComponentList *
00480 nsComponentsDlg::GetCompList()
00481 {
00482     if (mCompList)
00483         return mCompList;
00484 
00485     return NULL;
00486 }
00487 
00488 void
00489 nsComponentsDlg::RowSelected(GtkWidget *aWidget, gint aRow, gint aColumn,
00490                              GdkEventButton *aEvent, gpointer aData)
00491 {
00492     DUMP("RowSelected");
00493 
00494     sCurrRowSelected = aRow;
00495 
00496     ToggleRowSelection(aWidget, aRow, aColumn);
00497 }
00498 
00499 gboolean
00500 nsComponentsDlg::KeyPressed(GtkWidget *aWidget, GdkEventKey *aEvent, 
00501                             gpointer aData)
00502 {
00503   DUMP("KeyPressed");
00504 
00505   if (aEvent->keyval == GDK_space)
00506       ToggleRowSelection(aWidget, sCurrRowSelected, 0);
00507 
00508   return FALSE;
00509 }
00510 
00511 void
00512 nsComponentsDlg::ToggleRowSelection(GtkWidget *aWidget, gint aRow, 
00513                                     gint aColumn)
00514 {
00515     int numRows = 0, currRow = 0;
00516     GtkStyle *style = NULL;
00517     GdkBitmap *ch_mask = NULL;
00518     GdkPixmap *checked = NULL;
00519     GdkBitmap *un_mask = NULL;
00520     GdkPixmap *unchecked = NULL;
00521     nsComponent *currComp = sCustomST->GetComponents()->GetHead();
00522     
00523     style = gtk_widget_get_style(gCtx->window);
00524     checked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &ch_mask, 
00525               &style->bg[GTK_STATE_NORMAL], (gchar **)check_on_xpm);
00526     unchecked = gdk_pixmap_create_from_xpm_d(gCtx->window->window, &un_mask,
00527                 &style->bg[GTK_STATE_NORMAL], (gchar **)check_off_xpm);
00528 
00529     numRows = sCustomST->GetComponents()->GetLengthVisible();
00530     while ((currRow < numRows) && currComp) // paranoia!
00531     {
00532         if (!currComp->IsInvisible())
00533         {
00534             if (aRow == currRow)
00535             {
00536                 // update long desc
00537                 gtk_label_set_text(GTK_LABEL(sDescLong),
00538                                    currComp->GetDescLong());
00539                 gtk_widget_show(sDescLong);
00540 
00541                 // don't toggle checkbox for clicks on component text
00542                 if (aColumn != 0)
00543                    break;
00544 
00545                 if (currComp->IsSelected())
00546                 {
00547                     DUMP("Toggling off...");
00548                     currComp->SetUnselected();
00549                 }
00550                 else
00551                 {
00552                     DUMP("Toggling on...");
00553                     currComp->SetSelected();
00554                 }
00555                 currComp->ResolveDependees(currComp->IsSelected(),
00556                                             sCustomST->GetComponents());
00557                 break;
00558             }
00559             currRow++;
00560         }
00561         currComp = sCustomST->GetComponents()->GetNext();
00562     }
00563 
00564     // after resolving dependees redraw all checkboxes in one fell swoop
00565     currRow = 0;
00566     currComp = sCustomST->GetComponents()->GetHead();
00567     while ((currRow < numRows) && currComp) // paranoia!
00568     {
00569         if (!currComp->IsInvisible())
00570         {
00571             if (currComp->IsSelected())
00572             {
00573                 gtk_clist_set_pixmap(GTK_CLIST(aWidget), currRow, 0, 
00574                                      checked, ch_mask);
00575             }
00576             else
00577             {
00578                 gtk_clist_set_pixmap(GTK_CLIST(aWidget), currRow, 0, 
00579                                      unchecked, un_mask);
00580             }
00581             currRow++;
00582         }
00583         currComp = sCustomST->GetComponents()->GetNext();
00584     }
00585 }