]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/admindlg.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / admindlg.cpp
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 // Copyright (C) 2003 John Dallaway
6 //
7 // This program is part of the eCos host tools.
8 //
9 // This program is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by the Free
11 // Software Foundation; either version 2 of the License, or (at your option)
12 // any later version.
13 //
14 // This program is distributed in the hope that it will be useful, but WITHOUT
15 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17 // more details.
18 //
19 // You should have received a copy of the GNU General Public License along with
20 // this program; if not, write to the Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 //
23 // ----------------------------------------------------------------------------
24 //
25 //####COPYRIGHTEND####
26 // admindlg.cpp :
27 //
28 //===========================================================================
29 //#####DESCRIPTIONBEGIN####
30 //
31 // Author(s):   julians,jld
32 // Contact(s):  julians
33 // Date:        2000/09/28
34 // Version:     $Id$
35 // Purpose:
36 // Description: Implementation file for ecAdminDialog
37 // Requires:
38 // Provides:
39 // See also:
40 // Known bugs:
41 // Usage:
42 //
43 //####DESCRIPTIONEND####
44 //
45 //===========================================================================
46
47 // ============================================================================
48 // declarations
49 // ============================================================================
50
51 // ----------------------------------------------------------------------------
52 // headers
53 // ----------------------------------------------------------------------------
54 #ifdef __GNUG__
55 #pragma implementation "admindlg.h"
56 #endif
57
58 // Includes other headers for precompiled compilation
59 #include "ecpch.h"
60
61 #ifdef __BORLANDC__
62 #pragma hdrstop
63 #endif
64
65 // For registry access functions in GetUserToolsPath
66 #ifdef __WXMSW__
67 #include <windows.h>
68 #include "wx/msw/winundef.h"
69 #endif
70
71 #include "wx/cshelp.h"
72 #include "wx/filedlg.h"
73 #include "wx/file.h"
74 #include "wx/filefn.h"
75 #include "wx/progdlg.h"
76
77 #include "configtool.h"
78 #include "admindlg.h"
79 #include "configtooldoc.h"
80 #include "licensedlg.h"
81 #include "ecutils.h"
82
83 #ifdef __WXGTK__
84 #include "bitmaps/package_open.xpm"
85 #include "bitmaps/package_version.xpm"
86 #endif
87
88 BEGIN_EVENT_TABLE(ecAdminDialog, ecDialog)
89     EVT_BUTTON(wxID_OK, ecAdminDialog::OnClose)
90     EVT_BUTTON(ecID_ADMIN_DIALOG_ADD, ecAdminDialog::OnAdd)
91     EVT_BUTTON(ecID_ADMIN_DIALOG_REMOVE, ecAdminDialog::OnRemove)
92     EVT_INIT_DIALOG(ecAdminDialog::OnInitDialog)
93 END_EVENT_TABLE()
94
95 // ----------------------------------------------------------------------------
96 // main frame
97 // ----------------------------------------------------------------------------
98
99 // Frame constructor
100 ecAdminDialog::ecAdminDialog(wxWindow* parent, const wxString& repository, const wxString& userTools):
101     m_imageList(16, 16, 1)
102 {
103     m_strRepository = repository;
104     m_strUserTools = userTools;
105         m_CdlPkgData = NULL;
106
107     SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
108
109     ecDialog::Create(parent, ecID_ADMIN_DIALOG, _("Administration"),
110         wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
111
112     CreateControls(this);
113
114     m_imageList.Add(wxICON(package_open));
115     m_imageList.Add(wxICON(package_version));
116     m_treeCtrl->SetImageList(& m_imageList);
117
118     Centre(wxBOTH);
119 }
120
121 ecAdminDialog::~ecAdminDialog()
122 {
123         ClearPackageTree ();
124
125         // free memory allocated to the CDL database
126
127         if (m_CdlPkgData)
128                 delete m_CdlPkgData;
129
130     m_treeCtrl->SetImageList(NULL);
131 }
132
133 void ecAdminDialog::OnInitDialog(wxInitDialogEvent& event)
134 {
135     // setup the path to the user tools (tar and gunzip)
136     
137     if ((! m_strUserTools.IsEmpty()) || FindUserToolsPath ()) // if the user tools can be located
138     {
139         wxString path;
140         wxGetEnv(wxT("PATH"), & path);
141         
142         // TODO: this may not work on all platforms
143         path = path + wxString(wxPATH_SEP) + m_strUserTools;
144         wxSetEnv(wxT("PATH"), path);
145     }
146     
147     // populate the package tree
148
149     if (!PopulatePackageTree (m_strRepository))
150     {
151         m_strRepository = wxT("");
152         // TODO
153         // OnPkgadminRepository (); // prompt the user for the repository location
154     }
155 }
156
157 void ecAdminDialog::CreateControls(wxWindow* parent)
158 {
159     m_treeCtrl = new wxTreeCtrl(parent, ecID_ADMIN_DIALOG_TREE,
160         wxDefaultPosition, wxSize(380, 290), wxTR_HAS_BUTTONS | wxSUNKEN_BORDER);
161
162     wxSizer *item0 = new wxBoxSizer( wxHORIZONTAL );
163
164     wxSizer *item1 = new wxBoxSizer( wxVERTICAL );
165
166     wxStaticText *item2 = new wxStaticText( parent, wxID_STATIC, _("&Installed packages:"), wxDefaultPosition, wxDefaultSize, 0 );
167     item1->Add( item2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
168
169     wxWindow *item3 = parent->FindWindow( ecID_ADMIN_DIALOG_TREE );
170     wxASSERT( item3 );
171     item1->Add( item3, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
172
173     item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
174
175     wxSizer *item4 = new wxBoxSizer( wxVERTICAL );
176
177     wxButton *item5 = new wxButton( parent, ecID_ADMIN_DIALOG_ADD, _("&Add..."), wxDefaultPosition, wxDefaultSize, 0 );
178     item4->Add( item5, 0, wxALIGN_CENTRE|wxALL, 5 );
179
180     wxButton *item6 = new wxButton( parent, ecID_ADMIN_DIALOG_REMOVE, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0 );
181     item4->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
182
183     item4->Add( 20, 20, 1, wxALIGN_CENTRE|wxALL, 5 );
184
185     wxButton *item7 = new wxButton( parent, wxID_OK, _("&Close"), wxDefaultPosition, wxDefaultSize, 0 );
186     item4->Add( item7, 0, wxALIGN_CENTRE|wxALL, 5 );
187
188 #ifdef __WXGTK__
189     wxButton *contextButton = new wxContextHelpButton( parent );
190     item4->Add( contextButton, 0, wxALIGN_CENTRE|wxALL, 5 );
191 #endif
192
193     item0->Add( item4, 0, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxTOP|wxBOTTOM, 5 );
194     
195     item7->SetDefault(); // Make Close the default button
196
197     parent->SetAutoLayout( TRUE );
198     parent->SetSizer( item0 );
199     parent->Layout();
200     item0->Fit( parent );
201     //item0->SetSizeHints( parent );
202
203     // Add context-sensitive help text
204     parent->FindWindow( ecID_ADMIN_DIALOG_TREE)->SetHelpText(_("Displays the set of packages currently in the eCos component repository."));
205     parent->FindWindow( ecID_ADMIN_DIALOG_ADD)->SetHelpText(_("Adds the contents of an eCos package file to the eCos component repository."));
206     parent->FindWindow( ecID_ADMIN_DIALOG_REMOVE)->SetHelpText(_("Removes the currently selected package from the eCos component repository."));
207     parent->FindWindow( wxID_OK )->SetHelpText(_("Closes the dialog and saves any changes you have made."));
208
209 #if __WXGTK__
210     parent->FindWindow( wxID_CONTEXT_HELP )->SetHelpText(_("Invokes context-sensitive help for the clicked-on window."));
211 #endif
212
213 }
214
215 void ecAdminDialog::OnAdd(wxCommandEvent& event)
216 {
217     wxString defaultDir; // TODO
218     wxString defaultFile;
219     wxString wildcard = wxT("eCos Package Files (*.epk)|*.epk");
220     wxFileDialog dlg(this, _("Open eCos Package Files"), defaultDir, defaultFile, wildcard, wxOPEN|wxMULTIPLE);
221
222     if (wxID_OK == dlg.ShowModal ())
223     {
224         bool bRepositoryChanged = FALSE;
225         //POSITION posPathName = dlg.GetStartPosition ();
226         wxArrayString filenames;
227         dlg.GetPaths(filenames);
228         size_t i;
229         for (i = (size_t) 0; i < filenames.GetCount(); i++)
230         {
231             wxString strPathName(filenames[i]);
232
233             if (!wxFileExists(strPathName))
234             {
235                 wxString msg;
236                 msg.Printf(_("Cannot open %s"), (const wxChar*) strPathName);
237                 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
238             }
239             else
240             {
241                 
242                 // get an eCos package distribution file
243                 
244                 // extract the licence file
245
246                 wxString strCommand;
247                 strCommand.Printf(wxT("add %s --extract_license"), (const wxChar*) strPathName);
248                 strCommand.Replace(wxT("\\"), wxT("/")); // backslashes -> forward slashes for Tcl_EvalFile
249                 EvalTclFile (3, strCommand, _("Adding package"));
250
251                 wxString strLicenseFile = m_strRepository + wxString(wxFILE_SEP_PATH) + wxT("pkgadd.txt");
252 #ifdef __WXMSW__
253                 strLicenseFile.Replace (wxT("/"), wxT("\\")); // forward slashes -> backslashes for Win32
254 #endif
255                 // read the license file
256
257                 wxFile fileLicenseFile;
258                 if (fileLicenseFile.Exists (strLicenseFile) && fileLicenseFile.Open (strLicenseFile, wxFile::read))
259                 {
260                     //TRACE (_T("License file found at %s\n"), strLicenseFile);
261                     const off_t dwLicenseLength = fileLicenseFile.Length ();
262                     char* pszBuffer = new char [dwLicenseLength + 1]; // allocate a buffer
263                     fileLicenseFile.Read ((void*) pszBuffer, dwLicenseLength);
264                     fileLicenseFile.Close ();
265                     wxRemoveFile (strLicenseFile); // delete the license file when read
266                     pszBuffer [dwLicenseLength] = 0; // terminate the string in the buffer
267                     wxString strLicenseText (pszBuffer); // copy into a wxString to convert to Unicode
268                     delete [] pszBuffer;
269 #ifdef __WXMSW__
270                     if (-1 == strLicenseText.Find (wxT("\r\n"))) // if the file has LF line endings...
271                         strLicenseText.Replace (_T("\n"), _T("\r\n")); // ... replace with CRLF line endings
272 #else
273                     strLicenseText.Replace (_T("\r"), wxEmptyString); // remove CR characters
274 #endif
275                     // display the license text
276
277                     ecLicenseDialog dlgLicense (strLicenseText, this, ecID_LICENSE_DIALOG, strPathName + _(" - Add Packages"));
278                     if (wxID_OK != dlgLicense.ShowModal ()) // if license not accepted by user
279                         continue; // try the next file
280                 }
281                 
282                 // add the contents of the package distribution file
283                 
284                 strCommand.Printf (wxT("add %s --accept_license"), (const wxChar*) strPathName);
285                 strCommand.Replace (wxT("\\"), wxT("/")); // backslashes -> forward slashes for Tcl_EvalFile
286                 if (! EvalTclFile (3, strCommand, _("Adding package")))  // if not successful
287                 {
288                     // try the next file
289                 }
290                 else
291                 {                
292                     bRepositoryChanged = TRUE;
293                 }
294             }
295         }
296         
297         // refresh the package tree only if necessary
298         
299         if (bRepositoryChanged && ! PopulatePackageTree (m_strRepository))
300         {
301         }
302     }
303 }
304
305 void ecAdminDialog::OnRemove(wxCommandEvent& event)
306 {
307     wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
308
309     const wxTreeItemId hTreeItem = treeCtrl->GetSelection ();
310     if (! hTreeItem || !hTreeItem.IsOk())
311         return;
312     
313     if (wxYES != wxMessageBox (_("The selected package will be deleted from the repository. Core eCos packages may be restored only by reinstalling eCos.\n\nDo you wish to continue?"),
314         _("Remove Package"), wxYES_NO | wxICON_EXCLAMATION))
315         return;
316
317     ecAdminItemData* data = (ecAdminItemData*) treeCtrl->GetItemData (hTreeItem);
318
319     if (data) // if a package node is selected
320     {
321         // remove all package version nodes
322
323         wxString pstrPackage(data->m_string);
324         
325         bool bStatus = TRUE;
326         long cookie;
327         wxTreeItemId hChildItem = treeCtrl->GetFirstChild (hTreeItem, cookie);
328         while (hChildItem && bStatus)
329         {
330             const wxTreeItemId hNextChildItem = treeCtrl->GetNextSibling (hChildItem);                  
331             bStatus = RemovePackageVersion (hChildItem);
332             hChildItem = hNextChildItem;
333         }
334         
335         // remove the package node
336         
337         if (bStatus)
338         {
339             treeCtrl->Delete (hTreeItem);
340         }
341     }
342     else // a version node is selected
343     {
344         // remove the version node
345         
346         const wxTreeItemId hParentItem = treeCtrl->GetParent (hTreeItem);
347         wxASSERT (hParentItem && hParentItem.IsOk() );
348         if (RemovePackageVersion (hTreeItem) && ! treeCtrl->ItemHasChildren (hParentItem)) // if the only version was deleted
349         {
350             // remove the package node
351             
352             treeCtrl->Delete (hParentItem); 
353         }
354     }
355 }
356
357 void ecAdminDialog::OnClose(wxCommandEvent& event)
358 {
359     event.Skip();
360 }
361
362 bool ecAdminDialog::FindUserToolsPath()
363 {
364 #ifdef __WXMSW__
365     HKEY hKey;
366     if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\eCos Configuration Tool\\Paths\\UserToolsDir"), 0, KEY_READ, &hKey))
367         return FALSE;
368     
369     TCHAR szBuffer [MAX_PATH + 1];
370     DWORD dwBufferLength = MAX_PATH + 1;
371     LONG lStatus = RegQueryValueEx (hKey, _T("Folder"), NULL, NULL, (LPBYTE) szBuffer, &dwBufferLength);
372     RegCloseKey (hKey);
373     if (ERROR_SUCCESS != lStatus)
374         return FALSE;
375     
376     m_strUserTools = szBuffer;
377     // TRACE (_T("User tools found at %s\n"), m_strUserTools);
378     return ! m_strUserTools.IsEmpty ();
379 #else
380     // wxMessageBox("Sorry, ecAdminDialog::FindUserToolsPath not implemented for this platform.");
381     return FALSE;
382 #endif
383 }
384
385 bool ecAdminDialog::RemovePackageVersion (wxTreeItemId hTreeItem)
386 {
387     wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
388
389     const wxTreeItemId hParentItem = treeCtrl->GetParent (hTreeItem);
390     wxASSERT (hParentItem);
391
392     ecAdminItemData* data = (ecAdminItemData*) treeCtrl->GetItemData (hParentItem);
393
394     wxASSERT( data );
395
396     if (!data)
397         return FALSE;
398
399     wxString pstrPackage = data->m_string ;
400
401     wxString strCommand;
402     wxString itemText(treeCtrl->GetItemText (hTreeItem));
403     strCommand.Printf (wxT("remove %s --version %s"), (const wxChar*) pstrPackage, (const wxChar*) itemText);
404     if (! EvalTclFile (3, strCommand, wxT("Removing package"))) // if not successful
405         return false;
406     
407     treeCtrl->Delete (hTreeItem); // remove the selected item from the tree
408
409     return TRUE;
410 }
411
412 void ecAdminDialog::ClearPackageTree ()
413 {
414     wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
415
416     wxTreeItemId hPackage = treeCtrl->GetRootItem ();
417     if (! hPackage.IsOk()) // if no packages in the tree...
418         return;     // ...nothing to do
419     
420     while (hPackage.IsOk())
421     {
422         const wxTreeItemId hNextPackage = treeCtrl->GetNextSibling(hPackage);
423         treeCtrl->Delete (hPackage);
424         hPackage = hNextPackage;
425     }
426 }
427
428 // Trivial handlers; otherwise CdlPackagesDatabaseBody::make asserts.
429 static void CdlErrorHandler (std::string message)
430 {
431 };
432
433 static void CdlWarningHandler (std::string message)
434 {
435 };
436
437
438 bool ecAdminDialog::PopulatePackageTree (const wxString& packageDatabase)
439 {
440     wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
441
442     // delete any existing CDL database
443     
444     if (m_CdlPkgData)
445     {
446         delete m_CdlPkgData;
447         m_CdlPkgData = NULL;
448     }
449     
450     // load the package database
451     
452     try
453     {
454         // Cdl asserts unless the handlers are present.
455         m_CdlPkgData = CdlPackagesDatabaseBody::make (ecUtils::UnicodeToStdStr (packageDatabase), &CdlErrorHandler, &CdlWarningHandler);
456     }
457     catch (CdlStringException exception)
458     {
459         wxString strMessage;
460         strMessage.Printf (_("Error loading database:\n\n%s"), (const wxChar*) wxString (exception.get_message ().c_str ()));
461         wxMessageBox(strMessage, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
462         return FALSE;
463     }
464     catch (...)
465     {
466         wxMessageBox(_("Error loading database"), (const wxChar*) wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
467         return FALSE;
468     }
469     
470     // clear the old package tree
471     
472     ClearPackageTree ();
473     
474     // Add a root item
475     wxTreeItemId rootId = m_treeCtrl->AddRoot(_("Packages"), 0, -1);
476
477     // populate the new package tree
478     
479     const std::vector<std::string>& packages = m_CdlPkgData->get_packages ();
480     for (std::vector<std::string>::const_iterator package = packages.begin (); package != packages.end (); package++)
481     {
482         // add a package node
483         
484         wxTreeItemId hPackage = treeCtrl->AppendItem (treeCtrl->GetRootItem(), wxString (m_CdlPkgData->get_package_aliases (*package) [0].c_str ()));
485         treeCtrl->SetItemData (hPackage, new ecAdminItemData(wxString (package->c_str ())));
486         treeCtrl->SetItemImage (hPackage, 0, wxTreeItemIcon_Normal);
487         treeCtrl->SetItemImage (hPackage, 0, wxTreeItemIcon_Selected);
488         treeCtrl->SetItemImage (hPackage, 0, wxTreeItemIcon_Expanded);
489         treeCtrl->SetItemImage (hPackage, 0, wxTreeItemIcon_SelectedExpanded);
490         
491         const std::vector<std::string>& versions = m_CdlPkgData->get_package_versions (* package);
492         for (std::vector<std::string>::const_iterator version = versions.begin (); version != versions.end (); version++)
493         {
494             // add a version node
495             const wxTreeItemId hVersion = treeCtrl->AppendItem ( hPackage, wxString (version->c_str ()));
496             treeCtrl->SetItemImage (hVersion, 1, wxTreeItemIcon_Normal);
497             treeCtrl->SetItemImage (hVersion, 1, wxTreeItemIcon_Selected);
498             treeCtrl->SetItemImage (hVersion, 1, wxTreeItemIcon_Expanded);
499             treeCtrl->SetItemImage (hVersion, 1, wxTreeItemIcon_SelectedExpanded);
500         }
501         treeCtrl->SortChildren (hPackage); // sort the version nodes
502     }
503     
504     treeCtrl->SortChildren (treeCtrl->GetRootItem()); // sort the package nodes
505     treeCtrl->Expand(treeCtrl->GetRootItem());
506     
507     return TRUE;
508 }
509
510
511 bool ecAdminDialog::EvalTclFile(int nargc, const wxString& Argv, const wxString& msg)
512 {
513     wxProgressDialog dlgWait(msg, _("Please wait..."), 100, this);
514
515     dlgWait.Update(50);
516
517 //TRACE (_T("Evaluating ecosadmin.tcl %s\n"), pszArgv);
518
519     // set up the data structure which is passed to the Tcl thread
520
521     wxString strArgc;
522     strArgc.Printf (wxT("%d"), nargc);
523     std::string argv0 = ecUtils::UnicodeToStdStr (m_strRepository) + "/ecosadmin.tcl";
524     std::string argv = ecUtils::UnicodeToStdStr (Argv);
525     std::string argc = ecUtils::UnicodeToStdStr (strArgc);
526
527     Tcl_Interp * interp = Tcl_CreateInterp ();
528
529 #ifdef __WXMSW__
530     Tcl_Channel outchan = Tcl_OpenFileChannel (interp, "nul", "a+", 777);
531     Tcl_SetStdChannel (outchan, TCL_STDOUT); // direct standard output to NUL:
532 #endif
533
534     const char * pszStatus = Tcl_SetVar (interp, "argv0", (char*) argv0.c_str(), 0);
535     pszStatus = Tcl_SetVar (interp, "argv", (char*) argv.c_str(), 0);
536     pszStatus = Tcl_SetVar (interp, "argc", (char*) argc.c_str(), 0);
537     pszStatus = Tcl_SetVar (interp, "gui_mode", "1", 0); // return errors in result string
538     int nStatus = Tcl_EvalFile (interp, (char*) argv0.c_str());
539     const char* result = Tcl_GetStringResult (interp);
540
541 #ifdef __WXMSW__
542     Tcl_SetStdChannel (NULL, TCL_STDOUT);
543     Tcl_UnregisterChannel (interp, outchan);
544 #endif
545
546     Tcl_DeleteInterp (interp);
547
548     wxString strErrorMessage (result);
549
550     // report any error
551     if (! strErrorMessage.IsEmpty ())
552     {
553         wxString msg (_("Command execution error:\n\n") + strErrorMessage);
554         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
555         return FALSE;
556     }
557     else if (TCL_OK != nStatus)
558     {
559         wxString msg (_("Command execution error"));
560         wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
561     return FALSE;
562     }
563
564     return TRUE;
565 }