comparison host/tools/pkgadmin/win32/PkgAdminDlg.cpp @ 76:435cced73e2f ecos-v1_3_1-release

eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
author jlarmour
date Tue, 28 Mar 2000 14:10:45 +0000
parents
children d397fc472bcf
comparison
equal deleted inserted replaced
75:41bf073c0c32 76:435cced73e2f
1 //####COPYRIGHTBEGIN####
2 //
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
11 // any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 // more details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //
24 //####COPYRIGHTEND####
25 // PkgAdminDlg.cpp : implementation file
26 //
27
28 #include "stdafx.h"
29
30 #include "PkgAdmin.h"
31 #include "PkgAdminDlg.h"
32 #include "PkgAdminLicenseDlg.h"
33 #include "PkgAdminTclWaitDlg.h"
34
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #undef THIS_FILE
38 static char THIS_FILE[] = __FILE__;
39 #endif
40
41 /////////////////////////////////////////////////////////////////////////////
42 // CPkgadminAboutDlg dialog used for App About
43
44 class CPkgadminAboutDlg : public CDialog
45 {
46 public:
47 CPkgadminAboutDlg();
48
49 // Dialog Data
50 //{{AFX_DATA(CPkgadminAboutDlg)
51 enum { IDD = IDD_PKGADMIN_ABOUTBOX };
52 //}}AFX_DATA
53
54 // ClassWizard generated virtual function overrides
55 //{{AFX_VIRTUAL(CPkgadminAboutDlg)
56 protected:
57 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
58 //}}AFX_VIRTUAL
59
60 // Implementation
61 protected:
62 //{{AFX_MSG(CPkgadminAboutDlg)
63 //}}AFX_MSG
64 DECLARE_MESSAGE_MAP()
65 };
66
67 CPkgadminAboutDlg::CPkgadminAboutDlg() : CDialog(CPkgadminAboutDlg::IDD)
68 {
69 //{{AFX_DATA_INIT(CPkgadminAboutDlg)
70 //}}AFX_DATA_INIT
71 }
72
73 void CPkgadminAboutDlg::DoDataExchange(CDataExchange* pDX)
74 {
75 CDialog::DoDataExchange(pDX);
76 //{{AFX_DATA_MAP(CPkgadminAboutDlg)
77 //}}AFX_DATA_MAP
78 }
79
80 BEGIN_MESSAGE_MAP(CPkgadminAboutDlg, CDialog)
81 //{{AFX_MSG_MAP(CPkgadminAboutDlg)
82 // No message handlers
83 //}}AFX_MSG_MAP
84 END_MESSAGE_MAP()
85
86 /////////////////////////////////////////////////////////////////////////////
87 // CPkgAdminDlg dialog
88
89 CPkgAdminDlg::CPkgAdminDlg(LPCTSTR pszRepository,LPCTSTR pszUserTools)
90 : CeCosDialog(CPkgAdminDlg::IDD, NULL)
91 {
92 //{{AFX_DATA_INIT(CPkgAdminDlg)
93 // NOTE: the ClassWizard will add member initialization here
94 //}}AFX_DATA_INIT
95 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
96 if(pszRepository){
97 m_strRepository=pszRepository;
98 }
99 if(pszUserTools){
100 m_strUserTools=pszUserTools;
101 }
102 m_CdlPkgData = NULL;
103 }
104
105 void CPkgAdminDlg::DoDataExchange(CDataExchange* pDX)
106 {
107 CeCosDialog::DoDataExchange(pDX);
108 //{{AFX_DATA_MAP(CPkgAdminDlg)
109 DDX_Control(pDX, IDC_PKGADMIN_REMOVE, m_btnRemove);
110 DDX_Control(pDX, IDC_PKGADMIN_TREE, m_ctrlPackageTree);
111 //}}AFX_DATA_MAP
112 }
113
114 BEGIN_MESSAGE_MAP(CPkgAdminDlg, CeCosDialog)
115 //{{AFX_MSG_MAP(CPkgAdminDlg)
116 ON_WM_SYSCOMMAND()
117 ON_WM_PAINT()
118 ON_WM_QUERYDRAGICON()
119 ON_BN_CLICKED(IDC_PKGADMIN_REMOVE, OnPkgadminRemove)
120 ON_WM_DESTROY()
121 ON_BN_CLICKED(IDC_PKGADMIN_ADD, OnPkgadminAdd)
122 ON_BN_CLICKED(IDCLOSE, OnClose)
123 ON_BN_CLICKED(IDC_PKGADMIN_REPOSITORY, OnPkgadminRepository)
124 ON_NOTIFY(TVN_SELCHANGED, IDC_PKGADMIN_TREE, OnSelchangedPkgadminTree)
125 //}}AFX_MSG_MAP
126 END_MESSAGE_MAP()
127
128 /////////////////////////////////////////////////////////////////////////////
129 // CPkgAdminDlg message handlers
130
131 BOOL CPkgAdminDlg::OnInitDialog()
132 {
133 CeCosDialog::OnInitDialog();
134
135 if(this==AfxGetApp()->m_pMainWnd){ // only if the dialog is the application
136 // Add "About..." menu item to system menu.
137
138 // IDM_ABOUTBOX must be in the system command range.
139 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
140 ASSERT(IDM_ABOUTBOX < 0xF000);
141
142 CMenu* pSysMenu = GetSystemMenu(FALSE);
143 if (pSysMenu != NULL)
144 {
145 CString strAboutMenu;
146 strAboutMenu.LoadString(IDS_ABOUTBOX);
147 if (!strAboutMenu.IsEmpty())
148 {
149 pSysMenu->AppendMenu(MF_SEPARATOR);
150 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
151 }
152 }
153
154 // Set the icon for this dialog. The framework does this automatically
155 // when the application's main window is not a dialog
156 SetIcon(m_hIcon, TRUE); // Set big icon
157
158 // The following AppWizard-generated call was causing the 32x32 icon to
159 // be resized for use as a 16x16 icon. Removing the call causes the
160 // correct 16x16 icon to be displayed.
161 // SetIcon(m_hIcon, FALSE); // Set small icon
162
163 // TODO: Add extra initialization here
164
165 // setup the repsoitory location
166
167 if (m_strRepository.IsEmpty()) // if the repository cannot be located
168 {
169 OnPkgadminRepository (); // prompt the user for the repository location
170 if (m_strRepository.IsEmpty ())
171 {
172 PostMessage (WM_COMMAND,IDCANCEL);
173 return TRUE;
174 }
175 }
176 } else {
177 GetDlgItem(IDC_PKGADMIN_REPOSITORY)->ShowWindow(SW_HIDE);
178 }
179
180 // setup the path to the user tools (tar and gunzip)
181
182 if ((! m_strUserTools.IsEmpty()) || FindUserToolsPath ()) // if the user tools can be located
183 {
184 // add the user tools to the PATH environment variable
185 const DWORD nLength = GetEnvironmentVariable (_T("PATH"), NULL, 0) + 1;
186 TCHAR * pszOldPath = new TCHAR [nLength];
187 GetEnvironmentVariable (_T("PATH"), pszOldPath, nLength);
188 SetEnvironmentVariable (_T("PATH"), CString (pszOldPath) + _T(";") + m_strUserTools);
189 delete [] pszOldPath;
190 }
191
192 // setup the package tree image list
193
194 m_ilTreeIcons.Create (IDB_PKGADMIN_TREEICONS, 16, 1, RGB (0,128,128));
195 m_ctrlPackageTree.SetImageList (&m_ilTreeIcons, TVSIL_NORMAL);
196
197 // populate the package tree
198
199 while (! PopulatePackageTree (m_strRepository))
200 {
201 m_strRepository = _T("");
202 OnPkgadminRepository (); // prompt the user for the repository location
203 if (m_strRepository.IsEmpty ()) // if dialog was cancelled
204 {
205 PostQuitMessage (1);
206 return TRUE;
207 }
208 }
209
210 return TRUE; // return TRUE unless you set the focus to a control
211 }
212
213 void CPkgAdminDlg::OnSysCommand(UINT nID, LPARAM lParam)
214 {
215 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
216 {
217 CPkgadminAboutDlg dlgAbout;
218 dlgAbout.DoModal();
219 }
220 else
221 {
222 CeCosDialog::OnSysCommand(nID, lParam);
223 }
224 }
225
226 // If you add a minimize button to your dialog, you will need the code below
227 // to draw the icon. For MFC applications using the document/view model,
228 // this is automatically done for you by the framework.
229
230 void CPkgAdminDlg::OnPaint()
231 {
232 if (IsIconic())
233 {
234 CPaintDC dc(this); // device context for painting
235
236 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
237
238 // Center icon in client rectangle
239 int cxIcon = GetSystemMetrics(SM_CXICON);
240 int cyIcon = GetSystemMetrics(SM_CYICON);
241 CRect rect;
242 GetClientRect(&rect);
243 int x = (rect.Width() - cxIcon + 1) / 2;
244 int y = (rect.Height() - cyIcon + 1) / 2;
245
246 // Draw the icon
247 dc.DrawIcon(x, y, m_hIcon);
248 }
249 else
250 {
251 CeCosDialog::OnPaint();
252 }
253 }
254
255 // The system calls this to obtain the cursor to display while the user drags
256 // the minimized window.
257 HCURSOR CPkgAdminDlg::OnQueryDragIcon()
258 {
259 return (HCURSOR) m_hIcon;
260 }
261
262 bool CPkgAdminDlg::PopulatePackageTree(LPCTSTR pszPackagesPath)
263 {
264 // delete any existing CDL database
265
266 if (m_CdlPkgData)
267 {
268 delete m_CdlPkgData;
269 m_CdlPkgData = NULL;
270 }
271
272 // load the package database
273
274 try
275 {
276 m_CdlPkgData = CdlPackagesDatabaseBody::make (UnicodeToStdStr (pszPackagesPath));
277 }
278 catch (CdlStringException exception)
279 {
280 CString strMessage;
281 strMessage.Format (_T("Error loading database:\n\n%s"), CString (exception.get_message ().c_str ()));
282 AfxMessageBox (strMessage);
283 return false;
284 }
285 catch (...)
286 {
287 AfxMessageBox (_T("Error loading database"));
288 return false;
289 }
290
291 // clear the old package tree
292
293 ClearPackageTree ();
294
295 // populate the new package tree
296
297 const std::vector<std::string>& packages = m_CdlPkgData->get_packages ();
298 for (std::vector<std::string>::const_iterator package = packages.begin (); package != packages.end (); package++)
299 {
300 // add a package node
301
302 TRACE (_T("Adding package %s:"), CString (package->c_str ()));
303 HTREEITEM hPackage = m_ctrlPackageTree.InsertItem (CString (m_CdlPkgData->get_package_aliases (*package) [0].c_str ()));
304 m_ctrlPackageTree.SetItemData (hPackage, (DWORD) new CString (package->c_str ()));
305 m_ctrlPackageTree.SetItemImage (hPackage, 0, 0);
306
307 const std::vector<std::string>& versions = m_CdlPkgData->get_package_versions (* package);
308 for (std::vector<std::string>::const_iterator version = versions.begin (); version != versions.end (); version++)
309 {
310 // add a version node
311
312 TRACE (_T(" %s"), CString (version->c_str ()));
313 const HTREEITEM hVersion = m_ctrlPackageTree.InsertItem (CString (version->c_str ()), hPackage);
314 m_ctrlPackageTree.SetItemImage (hVersion, 1, 1);
315 }
316 TRACE (_T("\n"));
317 m_ctrlPackageTree.SortChildren (hPackage); // sort the version nodes
318 }
319
320 m_ctrlPackageTree.SortChildren (NULL); // sort the package nodes
321
322 if(this==AfxGetApp()->m_pMainWnd){ // if the dialog is the application
323 // update the caption bar
324 CString strCaption (m_strRepository);
325 strCaption.Replace (_TCHAR('/'), _TCHAR('\\'));
326 strCaption += _T(" - eCos Package Administration Tool");
327 SetWindowText (strCaption);
328 }
329
330 return true;
331 }
332
333 void CPkgAdminDlg::OnPkgadminRemove()
334 {
335 const HTREEITEM hTreeItem = m_ctrlPackageTree.GetSelectedItem ();
336 if (! hTreeItem)
337 return;
338
339 if (IDYES != CWnd::MessageBox (_T("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?"),
340 _T("Remove Package"), MB_YESNO | MB_ICONEXCLAMATION))
341 return;
342
343 const CString * pstrPackage = (const CString *) m_ctrlPackageTree.GetItemData (hTreeItem);
344 if (pstrPackage) // if a package node is selected
345 {
346 // remove all package version nodes
347
348 bool bStatus = true;
349 HTREEITEM hChildItem = m_ctrlPackageTree.GetChildItem (hTreeItem);
350 while (hChildItem && bStatus)
351 {
352 const HTREEITEM hNextChildItem = m_ctrlPackageTree.GetNextSiblingItem (hChildItem);
353 bStatus = RemovePackageVersion (hChildItem);
354 hChildItem = hNextChildItem;
355 }
356
357 // remove the package node
358
359 if (bStatus)
360 {
361 delete pstrPackage;
362 m_ctrlPackageTree.DeleteItem (hTreeItem);
363 }
364 }
365 else // a version node is selected
366 {
367 // remove the version node
368
369 const HTREEITEM hParentItem = m_ctrlPackageTree.GetParentItem (hTreeItem);
370 ASSERT (hParentItem);
371 if (RemovePackageVersion (hTreeItem) && ! m_ctrlPackageTree.ItemHasChildren (hParentItem)) // if the only version was deleted
372 {
373 // remove the package node
374
375 delete pstrPackage;
376 m_ctrlPackageTree.DeleteItem (hParentItem);
377 }
378 }
379 }
380
381 void CPkgAdminDlg::ClearPackageTree()
382 {
383 HTREEITEM hPackage = m_ctrlPackageTree.GetRootItem ();
384 if (! hPackage) // if no packages in the tree...
385 return; // ...nothing to do
386
387 while (hPackage)
388 {
389 const HTREEITEM hNextPackage = m_ctrlPackageTree.GetNextSiblingItem (hPackage);
390 TRACE (_T("Deleting package %s\n"), * ((CString *) m_ctrlPackageTree.GetItemData (hPackage)));
391 delete (CString *) m_ctrlPackageTree.GetItemData (hPackage);
392 m_ctrlPackageTree.DeleteItem (hPackage);
393 hPackage = hNextPackage;
394 }
395 }
396
397 void CPkgAdminDlg::OnDestroy()
398 {
399 CeCosDialog::OnDestroy();
400
401 // free memory allocated to the tree item data CStrings
402
403 ClearPackageTree ();
404
405 // free memory allocated to the CDL database
406
407 if (m_CdlPkgData)
408 delete m_CdlPkgData;
409
410 }
411
412 void CPkgAdminDlg::OnPkgadminAdd()
413 {
414 CFileDialog dlg (TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT, _T("eCos Package Files (*.epk)|*.epk||"), GetParent ());
415 TCHAR szBuffer [MAX_PATH * 16] = _T("");
416 dlg.m_ofn.lpstrFile = szBuffer;
417 dlg.m_ofn.nMaxFile = MAX_PATH * 16;
418 dlg.m_ofn.lpstrTitle = _T("Open eCos Package Files");
419 if (IDOK == dlg.DoModal ())
420 {
421 bool bRepositoryChanged = false;
422 POSITION posPathName = dlg.GetStartPosition ();
423 while (posPathName)
424 {
425 // get an eCos package distribution file
426
427 CString strPathName = dlg.GetNextPathName (posPathName);
428
429 // extract the licence file
430
431 CString strCommand;
432 strCommand.Format (_T("add %s --extract_license"), strPathName);
433 strCommand.Replace (_TCHAR('\\'), _TCHAR('/')); // backslashes -> forward slashes for Tcl_EvalFile
434 EvalTclFile (3, strCommand);
435 CString strLicenseFile = m_strRepository + _T("/pkgadd.txt");
436 strLicenseFile.Replace (_TCHAR('/'), _TCHAR('\\')); // forward slashes -> backslashes for Win32
437
438 // read the license file
439
440 CFile fileLicenseFile;
441 if (fileLicenseFile.Open (strLicenseFile, CFile::modeRead))
442 {
443 TRACE (_T("License file found at %s\n"), strLicenseFile);
444 const DWORD dwLicenseLength = fileLicenseFile.GetLength ();
445 char * pszBuffer = new char [dwLicenseLength + 1]; // allocate a buffer
446 fileLicenseFile.Read (pszBuffer, dwLicenseLength);
447 fileLicenseFile.Close ();
448 CFile::Remove (strLicenseFile); // delete the license file when read
449 pszBuffer [dwLicenseLength] = NULL; // terminate the string in the buffer
450 CString strLicenseText (pszBuffer); // copy into a CString to convert to Unicode
451 delete [] pszBuffer;
452 if (-1 == strLicenseText.Find (_T("\r\n"))) // if the file has LF line endings...
453 strLicenseText.Replace (_T("\n"), _T("\r\n")); // ... replace with CRLF line endings
454
455 // display the license text
456
457 CPkgAdminLicenseDlg dlgLicense (this);
458 dlgLicense.m_strLicense = strLicenseText;
459 dlgLicense.SetCaption (strPathName + _T(" - Add Packages"));
460 if (IDOK != dlgLicense.DoModal ()) // if license not accepted by user
461 continue; // try the next file
462 }
463
464 // add the contents of the package distribution file
465
466 strCommand.Format (_T("add %s --accept_license"), strPathName);
467 strCommand.Replace (_TCHAR('\\'), _TCHAR('/')); // backslashes -> forward slashes for Tcl_EvalFile
468 if (! EvalTclFile (3, strCommand)) // if not successful
469 continue; // try the next file
470
471 bRepositoryChanged = true;
472 }
473
474 // refresh the package tree only if necessary
475
476 if (bRepositoryChanged && ! PopulatePackageTree (m_strRepository))
477 DestroyWindow ();
478 }
479 }
480
481 bool CPkgAdminDlg::EvalTclFile(int nArgc, LPCTSTR pszArgv)
482 {
483 CPkgAdminTclWaitDlg dlgWait;
484
485 TRACE (_T("Evaluating ecosadmin.tcl %s\n"), pszArgv);
486
487 // set up the data structure which is passed to the Tcl thread
488
489 CString strArgc;
490 strArgc.Format (_T("%d"), nArgc);
491 std::string argv0 = UnicodeToStdStr (m_strRepository) + "/ecosadmin.tcl";
492 std::string argv = UnicodeToStdStr (pszArgv);
493 std::string argc = UnicodeToStdStr (strArgc);
494 dlgWait.etsInfo.argv0 = (char *) argv0.c_str ();
495 dlgWait.etsInfo.argv = (char *) argv.c_str ();
496 dlgWait.etsInfo.argc = (char *) argc.c_str ();
497
498 // display the 'please wait' dialog
499 // the Tcl command is invoked from CPkgAdminTclWaitDlg::OnCreate()
500
501 CWaitCursor curWait;
502 dlgWait.DoModal ();
503 curWait.Restore ();
504
505 // retrieve status information from the data structure
506
507 int nStatus = dlgWait.etsInfo.status;
508 CString strErrorMessage (dlgWait.etsInfo.result);
509
510 // report any error
511
512 if (! strErrorMessage.IsEmpty ())
513 {
514 AfxMessageBox (_T("Command execution error:\n\n") + strErrorMessage);
515 return false;
516 }
517 else if (TCL_OK != nStatus)
518 {
519 AfxMessageBox (_T("Command execution error"));
520 return false;
521 }
522
523 return true;
524 }
525
526 bool CPkgAdminDlg::RemovePackageVersion(HTREEITEM hTreeItem)
527 {
528 const HTREEITEM hParentItem = m_ctrlPackageTree.GetParentItem (hTreeItem);
529 ASSERT (hParentItem);
530 CString * pstrPackage = (CString *) m_ctrlPackageTree.GetItemData (hParentItem);
531 ASSERT (pstrPackage);
532 CString strCommand;
533 strCommand.Format (_T("remove %s --version %s"), * pstrPackage, m_ctrlPackageTree.GetItemText (hTreeItem));
534 if (! EvalTclFile (3, strCommand)) // if not successful
535 return false;
536
537 m_ctrlPackageTree.DeleteItem (hTreeItem); // remove the selected item from the tree
538 return true;
539 }
540
541 void CPkgAdminDlg::OnPkgadminRepository()
542 {
543 CFileDialog dlg (TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, _T("eCos Package Database Files (ecos.db)|ecos.db||"), GetParent ());
544 dlg.m_ofn.lpstrTitle = _T("Open eCos Package Database File");
545
546 int nStatus;
547 do
548 {
549 nStatus = dlg.DoModal ();
550 if (IDOK == nStatus)
551 {
552 const CString strPathName = dlg.GetPathName ();
553 const int nPathNameIndex = strPathName.ReverseFind (_TCHAR('\\'));
554 ASSERT (nPathNameIndex != -1);
555 m_strRepository = strPathName.Mid (0, nPathNameIndex);
556 m_strRepository.Replace (_TCHAR('\\'), _TCHAR('/'));
557 }
558 }
559 while ((IDOK == nStatus) && ! PopulatePackageTree (m_strRepository));
560 }
561
562 void CPkgAdminDlg::OnSelchangedPkgadminTree(NMHDR*, LRESULT* pResult)
563 {
564 //NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
565
566 // enable the remove button only if a node is selected
567 m_btnRemove.EnableWindow (NULL != m_ctrlPackageTree.GetSelectedItem ());
568
569 *pResult = 0;
570 }
571
572 std::string CPkgAdminDlg::UnicodeToStdStr(LPCTSTR str)
573 {
574 int nLength = 1 + _tcslen (str);
575 char * pszString = new char [nLength];
576
577 #ifdef _UNICODE
578 WideCharToMultiByte (CP_ACP, 0, str, -1, pszString, nLength, NULL, NULL);
579 #else
580 strcpy (pszString, str);
581 #endif
582
583 std::string stdstr = std::string (pszString);
584 delete [] pszString;
585 return stdstr;
586 }
587
588 bool CPkgAdminDlg::FindUserToolsPath()
589 {
590 HKEY hKey;
591 if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_CURRENT_USER, _T("Software\\Red Hat\\eCos\\Configuration Tool\\User Tools"), 0, KEY_READ, &hKey))
592 return false;
593
594 TCHAR szBuffer [MAX_PATH + 1];
595 DWORD dwBufferLength = MAX_PATH + 1;
596 LONG lStatus = RegQueryValueEx (hKey, _T("Folder"), NULL, NULL, (LPBYTE) szBuffer, &dwBufferLength);
597 RegCloseKey (hKey);
598 if (ERROR_SUCCESS != lStatus)
599 return false;
600
601 m_strUserTools = szBuffer;
602 TRACE (_T("User tools found at %s\n"), m_strUserTools);
603 return ! m_strUserTools.IsEmpty ();
604 }