1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 // Copyright (C) 2003 John Dallaway
7 // This program is part of the eCos host tools.
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)
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
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.
23 // ----------------------------------------------------------------------------
25 //####COPYRIGHTEND####
28 //===========================================================================
29 //#####DESCRIPTIONBEGIN####
31 // Author(s): julians,jld
32 // Contact(s): julians
36 // Description: Implementation file for ecAdminDialog
43 //####DESCRIPTIONEND####
45 //===========================================================================
47 // ============================================================================
49 // ============================================================================
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 #pragma implementation "admindlg.h"
58 // Includes other headers for precompiled compilation
65 // For registry access functions in GetUserToolsPath
68 #include "wx/msw/winundef.h"
71 #include "wx/cshelp.h"
72 #include "wx/filedlg.h"
74 #include "wx/filefn.h"
75 #include "wx/progdlg.h"
77 #include "configtool.h"
79 #include "configtooldoc.h"
80 #include "licensedlg.h"
84 #include "bitmaps/package_open.xpm"
85 #include "bitmaps/package_version.xpm"
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)
95 // ----------------------------------------------------------------------------
97 // ----------------------------------------------------------------------------
100 ecAdminDialog::ecAdminDialog(wxWindow* parent, const wxString& repository, const wxString& userTools):
101 m_imageList(16, 16, 1)
103 m_strRepository = repository;
104 m_strUserTools = userTools;
107 SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
109 ecDialog::Create(parent, ecID_ADMIN_DIALOG, _("Administration"),
110 wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
112 CreateControls(this);
114 m_imageList.Add(wxICON(package_open));
115 m_imageList.Add(wxICON(package_version));
116 m_treeCtrl->SetImageList(& m_imageList);
121 ecAdminDialog::~ecAdminDialog()
125 // free memory allocated to the CDL database
130 m_treeCtrl->SetImageList(NULL);
133 void ecAdminDialog::OnInitDialog(wxInitDialogEvent& event)
135 // setup the path to the user tools (tar and gunzip)
137 if ((! m_strUserTools.IsEmpty()) || FindUserToolsPath ()) // if the user tools can be located
140 wxGetEnv(wxT("PATH"), & path);
142 // TODO: this may not work on all platforms
143 path = path + wxString(wxPATH_SEP) + m_strUserTools;
144 wxSetEnv(wxT("PATH"), path);
147 // populate the package tree
149 if (!PopulatePackageTree (m_strRepository))
151 m_strRepository = wxT("");
153 // OnPkgadminRepository (); // prompt the user for the repository location
157 void ecAdminDialog::CreateControls(wxWindow* parent)
159 m_treeCtrl = new wxTreeCtrl(parent, ecID_ADMIN_DIALOG_TREE,
160 wxDefaultPosition, wxSize(380, 290), wxTR_HAS_BUTTONS | wxSUNKEN_BORDER);
162 wxSizer *item0 = new wxBoxSizer( wxHORIZONTAL );
164 wxSizer *item1 = new wxBoxSizer( wxVERTICAL );
166 wxStaticText *item2 = new wxStaticText( parent, wxID_STATIC, _("&Installed packages:"), wxDefaultPosition, wxDefaultSize, 0 );
167 item1->Add( item2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
169 wxWindow *item3 = parent->FindWindow( ecID_ADMIN_DIALOG_TREE );
171 item1->Add( item3, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
173 item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
175 wxSizer *item4 = new wxBoxSizer( wxVERTICAL );
177 wxButton *item5 = new wxButton( parent, ecID_ADMIN_DIALOG_ADD, _("&Add..."), wxDefaultPosition, wxDefaultSize, 0 );
178 item4->Add( item5, 0, wxALIGN_CENTRE|wxALL, 5 );
180 wxButton *item6 = new wxButton( parent, ecID_ADMIN_DIALOG_REMOVE, _("&Remove"), wxDefaultPosition, wxDefaultSize, 0 );
181 item4->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
183 item4->Add( 20, 20, 1, wxALIGN_CENTRE|wxALL, 5 );
185 wxButton *item7 = new wxButton( parent, wxID_OK, _("&Close"), wxDefaultPosition, wxDefaultSize, 0 );
186 item4->Add( item7, 0, wxALIGN_CENTRE|wxALL, 5 );
189 wxButton *contextButton = new wxContextHelpButton( parent );
190 item4->Add( contextButton, 0, wxALIGN_CENTRE|wxALL, 5 );
193 item0->Add( item4, 0, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxTOP|wxBOTTOM, 5 );
195 item7->SetDefault(); // Make Close the default button
197 parent->SetAutoLayout( TRUE );
198 parent->SetSizer( item0 );
200 item0->Fit( parent );
201 //item0->SetSizeHints( parent );
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."));
210 parent->FindWindow( wxID_CONTEXT_HELP )->SetHelpText(_("Invokes context-sensitive help for the clicked-on window."));
215 void ecAdminDialog::OnAdd(wxCommandEvent& event)
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);
222 if (wxID_OK == dlg.ShowModal ())
224 bool bRepositoryChanged = FALSE;
225 //POSITION posPathName = dlg.GetStartPosition ();
226 wxArrayString filenames;
227 dlg.GetPaths(filenames);
229 for (i = (size_t) 0; i < filenames.GetCount(); i++)
231 wxString strPathName(filenames[i]);
233 if (!wxFileExists(strPathName))
236 msg.Printf(_("Cannot open %s"), (const wxChar*) strPathName);
237 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
242 // get an eCos package distribution file
244 // extract the licence file
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"));
251 wxString strLicenseFile = m_strRepository + wxString(wxFILE_SEP_PATH) + wxT("pkgadd.txt");
253 strLicenseFile.Replace (wxT("/"), wxT("\\")); // forward slashes -> backslashes for Win32
255 // read the license file
257 wxFile fileLicenseFile;
258 if (fileLicenseFile.Exists (strLicenseFile) && fileLicenseFile.Open (strLicenseFile, wxFile::read))
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
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
273 strLicenseText.Replace (_T("\r"), wxEmptyString); // remove CR characters
275 // display the license text
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
282 // add the contents of the package distribution file
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
292 bRepositoryChanged = TRUE;
297 // refresh the package tree only if necessary
299 if (bRepositoryChanged && ! PopulatePackageTree (m_strRepository))
305 void ecAdminDialog::OnRemove(wxCommandEvent& event)
307 wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
309 const wxTreeItemId hTreeItem = treeCtrl->GetSelection ();
310 if (! hTreeItem || !hTreeItem.IsOk())
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))
317 ecAdminItemData* data = (ecAdminItemData*) treeCtrl->GetItemData (hTreeItem);
319 if (data) // if a package node is selected
321 // remove all package version nodes
323 wxString pstrPackage(data->m_string);
327 wxTreeItemId hChildItem = treeCtrl->GetFirstChild (hTreeItem, cookie);
328 while (hChildItem && bStatus)
330 const wxTreeItemId hNextChildItem = treeCtrl->GetNextSibling (hChildItem);
331 bStatus = RemovePackageVersion (hChildItem);
332 hChildItem = hNextChildItem;
335 // remove the package node
339 treeCtrl->Delete (hTreeItem);
342 else // a version node is selected
344 // remove the version node
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
350 // remove the package node
352 treeCtrl->Delete (hParentItem);
357 void ecAdminDialog::OnClose(wxCommandEvent& event)
362 bool ecAdminDialog::FindUserToolsPath()
366 if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\eCos Configuration Tool\\Paths\\UserToolsDir"), 0, KEY_READ, &hKey))
369 TCHAR szBuffer [MAX_PATH + 1];
370 DWORD dwBufferLength = MAX_PATH + 1;
371 LONG lStatus = RegQueryValueEx (hKey, _T("Folder"), NULL, NULL, (LPBYTE) szBuffer, &dwBufferLength);
373 if (ERROR_SUCCESS != lStatus)
376 m_strUserTools = szBuffer;
377 // TRACE (_T("User tools found at %s\n"), m_strUserTools);
378 return ! m_strUserTools.IsEmpty ();
380 // wxMessageBox("Sorry, ecAdminDialog::FindUserToolsPath not implemented for this platform.");
385 bool ecAdminDialog::RemovePackageVersion (wxTreeItemId hTreeItem)
387 wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
389 const wxTreeItemId hParentItem = treeCtrl->GetParent (hTreeItem);
390 wxASSERT (hParentItem);
392 ecAdminItemData* data = (ecAdminItemData*) treeCtrl->GetItemData (hParentItem);
399 wxString pstrPackage = data->m_string ;
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
407 treeCtrl->Delete (hTreeItem); // remove the selected item from the tree
412 void ecAdminDialog::ClearPackageTree ()
414 wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
416 wxTreeItemId hPackage = treeCtrl->GetRootItem ();
417 if (! hPackage.IsOk()) // if no packages in the tree...
418 return; // ...nothing to do
420 while (hPackage.IsOk())
422 const wxTreeItemId hNextPackage = treeCtrl->GetNextSibling(hPackage);
423 treeCtrl->Delete (hPackage);
424 hPackage = hNextPackage;
428 // Trivial handlers; otherwise CdlPackagesDatabaseBody::make asserts.
429 static void CdlErrorHandler (std::string message)
433 static void CdlWarningHandler (std::string message)
438 bool ecAdminDialog::PopulatePackageTree (const wxString& packageDatabase)
440 wxTreeCtrl* treeCtrl = (wxTreeCtrl*) FindWindow( ecID_ADMIN_DIALOG_TREE) ;
442 // delete any existing CDL database
450 // load the package database
454 // Cdl asserts unless the handlers are present.
455 m_CdlPkgData = CdlPackagesDatabaseBody::make (ecUtils::UnicodeToStdStr (packageDatabase), &CdlErrorHandler, &CdlWarningHandler);
457 catch (CdlStringException exception)
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);
466 wxMessageBox(_("Error loading database"), (const wxChar*) wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
470 // clear the old package tree
475 wxTreeItemId rootId = m_treeCtrl->AddRoot(_("Packages"), 0, -1);
477 // populate the new package tree
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++)
482 // add a package node
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);
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++)
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);
501 treeCtrl->SortChildren (hPackage); // sort the version nodes
504 treeCtrl->SortChildren (treeCtrl->GetRootItem()); // sort the package nodes
505 treeCtrl->Expand(treeCtrl->GetRootItem());
511 bool ecAdminDialog::EvalTclFile(int nargc, const wxString& Argv, const wxString& msg)
513 wxProgressDialog dlgWait(msg, _("Please wait..."), 100, this);
517 //TRACE (_T("Evaluating ecosadmin.tcl %s\n"), pszArgv);
519 // set up the data structure which is passed to the Tcl thread
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);
527 Tcl_Interp * interp = Tcl_CreateInterp ();
530 Tcl_Channel outchan = Tcl_OpenFileChannel (interp, "nul", "a+", 777);
531 Tcl_SetStdChannel (outchan, TCL_STDOUT); // direct standard output to NUL:
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);
542 Tcl_SetStdChannel (NULL, TCL_STDOUT);
543 Tcl_UnregisterChannel (interp, outchan);
546 Tcl_DeleteInterp (interp);
548 wxString strErrorMessage (result);
551 if (! strErrorMessage.IsEmpty ())
553 wxString msg (_("Command execution error:\n\n") + strErrorMessage);
554 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
557 else if (TCL_OK != nStatus)
559 wxString msg (_("Command execution error"));
560 wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);