1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxRegKey class demo
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
19 #include "wx/wxprec.h"
29 #include "wx/treectrl.h"
30 #include "wx/config.h"
31 #include "wx/imaglist.h"
32 #include "wx/tokenzr.h"
34 #if wxUSE_CONFIG_NATIVE && defined( __WXMSW__ )
40 // ----------------------------------------------------------------------------
42 // ----------------------------------------------------------------------------
43 class RegApp
: public wxApp
49 // ----------------------------------------------------------------------------
50 // image list with registry icons
51 // ----------------------------------------------------------------------------
52 class RegImageList
: public wxImageList
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
72 class RegTreeCtrl
: public wxTreeCtrl
76 RegTreeCtrl(wxWindow
*parent
, wxWindowID id
);
77 virtual ~RegTreeCtrl();
80 void OnDeleteItem (wxTreeEvent
& event
);
81 void OnItemExpanding (wxTreeEvent
& event
);
82 void OnSelChanged (wxTreeEvent
& event
);
84 void OnBeginEdit (wxTreeEvent
& event
);
85 void OnEndEdit (wxTreeEvent
& event
);
87 void OnBeginDrag (wxTreeEvent
& event
);
88 void OnEndDrag (wxTreeEvent
& event
);
90 void OnRightClick (wxMouseEvent
& event
);
91 void OnChar (wxKeyEvent
& event
);
92 void OnIdle (wxIdleEvent
& event
);
94 // forwarded notifications (by the frame)
98 void GoTo(const wxString
& location
);
100 void DeleteSelected();
101 void ShowProperties();
102 void CreateNewKey(const wxString
& strName
);
103 void CreateNewTextValue(const wxString
& strName
);
104 void CreateNewBinaryValue(const wxString
& strName
);
107 bool IsKeySelected() const;
110 // structure describing a registry key/value
111 class TreeNode
: public wxTreeItemData
113 WX_DEFINE_ARRAY_PTR(TreeNode
*, TreeChildren
);
115 RegTreeCtrl
*m_pTree
; // must be !NULL
116 TreeNode
*m_pParent
; // NULL only for the root node
117 wxTreeItemId m_id
; // the id of the tree control item
118 wxString m_strName
; // name of the key/value
119 TreeChildren m_aChildren
; // array of subkeys/values
120 bool m_bKey
; // key or value?
121 wxRegKey
*m_pKey
; // only may be !NULL if m_bKey == true
124 wxTreeItemId
Id() const { return m_id
; }
125 bool IsRoot() const { return m_pParent
== NULL
; }
126 bool IsKey() const { return m_bKey
; }
127 TreeNode
*Parent() const { return m_pParent
; }
135 bool DeleteChild(TreeNode
*child
);
136 void DestroyChildren();
137 const wxChar
*FullName() const;
139 // get the associated key: make sure the pointer is !NULL
140 wxRegKey
& Key() { if ( !m_pKey
) OnExpand(); return *m_pKey
; }
142 // dtor deletes all children
146 wxImageList
*m_imageList
;
147 wxMenu
*m_pMenuPopup
;
151 TreeNode
*m_draggedItem
; // the item being dragged
152 bool m_copyOnDrop
; // if false, then move
154 bool m_restoreStatus
; // after OnItemExpanding()
156 wxString m_nameOld
; // the initial value of item being renamed
158 TreeNode
*GetNode(const wxTreeEvent
& event
)
159 { return (TreeNode
*)GetItemData(event
.GetItem()); }
162 // create a new node and insert it to the tree
163 TreeNode
*InsertNewTreeNode(TreeNode
*pParent
,
164 const wxString
& strName
,
165 int idImage
= RegImageList::ClosedKey
,
166 const wxString
*pstrValue
= NULL
);
168 // add standard registry keys
172 DECLARE_EVENT_TABLE()
175 #endif // #if DO_REGTEST
177 // ----------------------------------------------------------------------------
178 // the main window of our application
179 // ----------------------------------------------------------------------------
180 class RegFrame
: public wxFrame
184 RegFrame(wxFrame
*parent
, const wxChar
*title
, int x
, int y
, int w
, int h
);
188 void OnQuit (wxCommandEvent
& event
);
189 void OnAbout(wxCommandEvent
& event
);
190 void OnTest (wxCommandEvent
& event
);
192 void OnGoTo (wxCommandEvent
& event
);
194 void OnExpand (wxCommandEvent
& event
);
195 void OnCollapse(wxCommandEvent
& event
);
196 void OnToggle (wxCommandEvent
& event
);
197 void OnRefresh (wxCommandEvent
& event
);
199 void OnDelete (wxCommandEvent
& event
);
200 void OnNewKey (wxCommandEvent
& event
);
201 void OnNewText (wxCommandEvent
& event
);
202 void OnNewBinary(wxCommandEvent
& event
);
204 void OnInfo (wxCommandEvent
& event
);
206 DECLARE_EVENT_TABLE()
211 RegTreeCtrl
*m_treeCtrl
;
215 // ----------------------------------------------------------------------------
217 // ----------------------------------------------------------------------------
239 // ----------------------------------------------------------------------------
241 // ----------------------------------------------------------------------------
243 BEGIN_EVENT_TABLE(RegFrame
, wxFrame
)
244 EVT_MENU(Menu_Test
, RegFrame::OnTest
)
245 EVT_MENU(Menu_About
, RegFrame::OnAbout
)
246 EVT_MENU(Menu_Quit
, RegFrame::OnQuit
)
247 EVT_MENU(Menu_GoTo
, RegFrame::OnGoTo
)
248 EVT_MENU(Menu_Expand
, RegFrame::OnExpand
)
249 EVT_MENU(Menu_Collapse
, RegFrame::OnCollapse
)
250 EVT_MENU(Menu_Toggle
, RegFrame::OnToggle
)
251 EVT_MENU(Menu_Refresh
, RegFrame::OnRefresh
)
252 EVT_MENU(Menu_Delete
, RegFrame::OnDelete
)
253 EVT_MENU(Menu_NewKey
, RegFrame::OnNewKey
)
254 EVT_MENU(Menu_NewText
, RegFrame::OnNewText
)
255 EVT_MENU(Menu_NewBinary
,RegFrame::OnNewBinary
)
256 EVT_MENU(Menu_Info
, RegFrame::OnInfo
)
261 BEGIN_EVENT_TABLE(RegTreeCtrl
, wxTreeCtrl
)
262 EVT_TREE_DELETE_ITEM (Ctrl_RegTree
, RegTreeCtrl::OnDeleteItem
)
263 EVT_TREE_ITEM_EXPANDING (Ctrl_RegTree
, RegTreeCtrl::OnItemExpanding
)
264 EVT_TREE_ITEM_COLLAPSING(Ctrl_RegTree
, RegTreeCtrl::OnItemExpanding
)
265 EVT_TREE_SEL_CHANGED (Ctrl_RegTree
, RegTreeCtrl::OnSelChanged
)
267 EVT_TREE_BEGIN_LABEL_EDIT(Ctrl_RegTree
, RegTreeCtrl::OnBeginEdit
)
268 EVT_TREE_END_LABEL_EDIT (Ctrl_RegTree
, RegTreeCtrl::OnEndEdit
)
270 EVT_TREE_BEGIN_DRAG (Ctrl_RegTree
, RegTreeCtrl::OnBeginDrag
)
271 EVT_TREE_BEGIN_RDRAG (Ctrl_RegTree
, RegTreeCtrl::OnBeginDrag
)
272 EVT_TREE_END_DRAG (Ctrl_RegTree
, RegTreeCtrl::OnEndDrag
)
274 EVT_CHAR (RegTreeCtrl::OnChar
)
275 EVT_RIGHT_DOWN(RegTreeCtrl::OnRightClick
)
276 EVT_IDLE (RegTreeCtrl::OnIdle
)
281 // ============================================================================
283 // ============================================================================
285 // ----------------------------------------------------------------------------
287 // ----------------------------------------------------------------------------
289 // create the "registry operations" menu
290 wxMenu
*CreateRegistryMenu()
292 wxMenu
*pMenuNew
= new wxMenu
;
293 pMenuNew
->Append(Menu_NewKey
, wxT("&Key"), wxT("Create a new key"));
294 pMenuNew
->AppendSeparator();
295 pMenuNew
->Append(Menu_NewText
, wxT("&Text value"), wxT("Create a new text value"));
296 pMenuNew
->Append(Menu_NewBinary
, wxT("&Binary value"), wxT("Create a new binary value"));
298 wxMenu
*pMenuReg
= new wxMenu
;
299 pMenuReg
->Append(Menu_New
, wxT("&New"), pMenuNew
);
300 pMenuReg
->Append(Menu_Delete
, wxT("&Delete..."), wxT("Delete selected key/value"));
301 pMenuReg
->AppendSeparator();
302 pMenuReg
->Append(Menu_GoTo
, wxT("&Go to...\tCtrl-G"), wxT("Go to registry key"));
303 pMenuReg
->Append(Menu_Expand
, wxT("&Expand"), wxT("Expand current key"));
304 pMenuReg
->Append(Menu_Collapse
, wxT("&Collapse"), wxT("Collapse current key"));
305 pMenuReg
->Append(Menu_Toggle
, wxT("&Toggle"), wxT("Toggle current key"));
306 pMenuReg
->AppendSeparator();
307 pMenuReg
->Append(Menu_Refresh
, wxT("&Refresh"), wxT("Refresh the subtree"));
308 pMenuReg
->AppendSeparator();
309 pMenuReg
->Append(Menu_Info
, wxT("&Properties"),wxT("Information about current selection"));
314 // ----------------------------------------------------------------------------
316 // ----------------------------------------------------------------------------
317 IMPLEMENT_APP(RegApp
)
319 // `Main program' equivalent, creating windows and returning main app frame
320 bool RegApp::OnInit()
322 if ( !wxApp::OnInit() )
325 // create the main frame window and show it
326 RegFrame
*frame
= new RegFrame(NULL
, wxT("wxRegTest"), 50, 50, 600, 350);
334 // ----------------------------------------------------------------------------
336 // ----------------------------------------------------------------------------
338 RegFrame::RegFrame(wxFrame
*parent
, const wxChar
*title
, int x
, int y
, int w
, int h
)
339 : wxFrame(parent
, wxID_ANY
, title
, wxPoint(x
, y
), wxSize(w
, h
))
341 // this reduces flicker effects
342 SetBackgroundColour(wxColour(255, 255, 255));
346 SetIcon(wxIcon(wxT("app_icon")));
350 wxMenu
*pMenuFile
= new wxMenu
;
351 pMenuFile
->Append(Menu_Test
, wxT("Te&st"), wxT("Test key creation"));
352 pMenuFile
->AppendSeparator();
353 pMenuFile
->Append(Menu_About
, wxT("&About..."), wxT("Show an extraordinarly beautiful dialog"));
354 pMenuFile
->AppendSeparator();
355 pMenuFile
->Append(Menu_Quit
, wxT("E&xit"), wxT("Quit this program"));
357 wxMenuBar
*pMenu
= new wxMenuBar
;
358 pMenu
->Append(pMenuFile
, wxT("&File"));
359 pMenu
->Append(CreateRegistryMenu(), wxT("&Registry"));
363 // create child controls
364 // ---------------------
365 m_treeCtrl
= new RegTreeCtrl(this, Ctrl_RegTree
);
369 // create the status line
370 // ----------------------
372 #endif // wxUSE_STATUSBAR
375 RegFrame::~RegFrame()
378 // this makes deletion of it *much* quicker
383 void RegFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
388 void RegFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
390 wxMessageDialog
dialog(this,
391 wxT("wxRegistry sample\n")
392 wxT("(c) 1998, 2000 Vadim Zeitlin"),
393 wxT("About wxRegTest"), wxOK
);
398 void RegFrame::OnTest(wxCommandEvent
& WXUNUSED(event
))
401 m_treeCtrl
->OnMenuTest();
405 void RegFrame::OnGoTo(wxCommandEvent
& WXUNUSED(event
))
407 static wxString s_location
= wxT("HKEY_CURRENT_USER\\Software\\wxWidgets");
409 wxString location
= wxGetTextFromUser(
410 wxT("Enter the location to go to:"),
411 wxT("wxRegTest question"),
418 s_location
= location
;
420 m_treeCtrl
->GoTo(location
);
424 void RegFrame::OnExpand(wxCommandEvent
& WXUNUSED(event
))
427 m_treeCtrl
->Expand(m_treeCtrl
->GetSelection());
431 void RegFrame::OnCollapse(wxCommandEvent
& WXUNUSED(event
))
434 m_treeCtrl
->Collapse(m_treeCtrl
->GetSelection());
438 void RegFrame::OnToggle(wxCommandEvent
& WXUNUSED(event
))
441 m_treeCtrl
->Toggle(m_treeCtrl
->GetSelection());
445 void RegFrame::OnRefresh(wxCommandEvent
& WXUNUSED(event
))
448 m_treeCtrl
->DoRefresh();
452 void RegFrame::OnDelete(wxCommandEvent
& WXUNUSED(event
))
455 m_treeCtrl
->DeleteSelected();
459 void RegFrame::OnNewKey(wxCommandEvent
& WXUNUSED(event
))
462 if ( m_treeCtrl
->IsKeySelected() )
464 m_treeCtrl
->CreateNewKey(
465 wxGetTextFromUser(wxT("Enter the name of the new key")));
470 void RegFrame::OnNewText(wxCommandEvent
& WXUNUSED(event
))
473 if ( m_treeCtrl
->IsKeySelected() )
475 m_treeCtrl
->CreateNewTextValue(
476 wxGetTextFromUser(wxT("Enter the name for the new text value")));
481 void RegFrame::OnNewBinary(wxCommandEvent
& WXUNUSED(event
))
484 if ( m_treeCtrl
->IsKeySelected() )
486 m_treeCtrl
->CreateNewBinaryValue(
487 wxGetTextFromUser(wxT("Enter the name for the new binary value")));
492 void RegFrame::OnInfo(wxCommandEvent
& WXUNUSED(event
))
495 m_treeCtrl
->ShowProperties();
499 // ----------------------------------------------------------------------------
501 // ----------------------------------------------------------------------------
502 RegImageList::RegImageList() : wxImageList(16, 16, true)
504 // should be in sync with enum RegImageList::RegIcon
505 static const wxChar
*aszIcons
[] = { wxT("key1"),wxT("key2"),wxT("key3"),wxT("value1"),wxT("value2") };
506 wxString str
= wxT("icon_");
507 for ( unsigned int n
= 0; n
< WXSIZEOF(aszIcons
); n
++ )
509 Add(wxIcon(str
+ aszIcons
[n
], wxBITMAP_TYPE_ICO_RESOURCE
));
515 // ----------------------------------------------------------------------------
517 // ----------------------------------------------------------------------------
519 // create a new tree item and insert it into the tree
520 RegTreeCtrl::TreeNode
*RegTreeCtrl::InsertNewTreeNode(TreeNode
*pParent
,
521 const wxString
& strName
,
523 const wxString
*pstrValue
)
525 // create new item & insert it
526 TreeNode
*pNewNode
= new TreeNode
;
527 pNewNode
->m_pTree
= this;
528 pNewNode
->m_pParent
= pParent
;
529 pNewNode
->m_strName
= strName
;
530 pNewNode
->m_bKey
= pstrValue
== NULL
;
531 pNewNode
->m_pKey
= NULL
;
534 pNewNode
->m_id
= AppendItem(pParent
->Id(),
535 pNewNode
->IsKey() ? strName
: *pstrValue
,
540 pNewNode
->m_id
= AddRoot(strName
);
543 wxASSERT_MSG( pNewNode
->m_id
, wxT("can't create tree control item!"));
545 // save the pointer in the item
546 SetItemData(pNewNode
->m_id
, pNewNode
);
548 // add it to the list of parent's children
549 if ( pParent
!= NULL
)
551 pParent
->m_aChildren
.Add(pNewNode
);
554 if ( pNewNode
->IsKey() )
556 SetItemHasChildren(pNewNode
->Id());
558 if ( !pNewNode
->IsRoot() )
560 // set the expanded icon as well
561 SetItemImage(pNewNode
->Id(),
562 RegImageList::OpenedKey
,
563 wxTreeItemIcon_Expanded
);
570 RegTreeCtrl::RegTreeCtrl(wxWindow
*parent
, wxWindowID id
)
571 : wxTreeCtrl(parent
, id
, wxDefaultPosition
, wxDefaultSize
,
572 wxTR_HAS_BUTTONS
| wxTR_EDIT_LABELS
| wxSUNKEN_BORDER
)
575 m_draggedItem
= NULL
;
576 m_restoreStatus
= false;
578 // create the image list
579 // ---------------------
580 m_imageList
= new RegImageList
;
581 SetImageList(m_imageList
);
585 m_pRoot
= InsertNewTreeNode(NULL
, wxT("Registry Root"), RegImageList::Root
);
589 m_pMenuPopup
= CreateRegistryMenu();
592 RegTreeCtrl::~RegTreeCtrl()
595 // delete m_pRoot; -- this is done by the tree now
599 void RegTreeCtrl::AddStdKeys()
601 for ( unsigned int ui
= 0; ui
< wxRegKey::nStdKeys
; ui
++ )
603 InsertNewTreeNode(m_pRoot
, wxRegKey::GetStdKeyName(ui
));
607 // ----------------------------------------------------------------------------
609 // ----------------------------------------------------------------------------
611 void RegTreeCtrl::OnIdle(wxIdleEvent
& WXUNUSED(event
))
613 if ( m_restoreStatus
)
615 // restore it after OnItemExpanding()
616 wxLogStatus(wxT("Ok"));
617 wxSetCursor(*wxSTANDARD_CURSOR
);
619 m_restoreStatus
= false;
623 void RegTreeCtrl::OnRightClick(wxMouseEvent
& event
)
626 wxTreeItemId lId
= HitTest(wxPoint(event
.GetX(), event
.GetY()), iFlags
);
627 if ( iFlags
& wxTREE_HITTEST_ONITEMLABEL
)
629 // select the item first
632 //else: take the currently selected item if click not on item
634 PopupMenu(m_pMenuPopup
, event
.GetX(), event
.GetY());
638 void RegTreeCtrl::OnDeleteItem(wxTreeEvent
& WXUNUSED(event
))
642 // test the key creation functions
643 void RegTreeCtrl::OnMenuTest()
645 wxTreeItemId lId
= GetSelection();
646 TreeNode
*pNode
= (TreeNode
*)GetItemData(lId
);
648 wxCHECK_RET( pNode
!= NULL
, wxT("tree item without data?") );
650 if ( pNode
->IsRoot() )
652 wxLogError(wxT("Can't create a subkey under the root key."));
656 if ( !pNode
->IsKey() )
658 wxLogError(wxT("Can't create a subkey under a value!"));
662 wxRegKey
key1(pNode
->Key(), wxT("key1"));
665 wxRegKey
key2a(key1
, wxT("key2a")), key2b(key1
, wxT("key2b"));
666 if ( key2a
.Create() && key2b
.Create() )
668 // put some values under the newly created keys
669 key1
.SetValue(wxT("first_term"), wxT("10"));
670 key1
.SetValue(wxT("second_term"), wxT("7"));
671 key2a
= wxT("this is the unnamed value");
672 key2b
.SetValue(wxT("sum"), 17);
676 wxLogStatus(wxT("Test keys successfully added."));
681 wxLogError(wxT("Creation of test keys failed."));
684 void RegTreeCtrl::OnChar(wxKeyEvent
& event
)
686 switch ( event
.GetKeyCode() )
693 if ( event
.AltDown() )
704 void RegTreeCtrl::OnSelChanged(wxTreeEvent
& event
)
707 wxFrame
*pFrame
= (wxFrame
*) wxWindow::GetParent();
708 pFrame
->SetStatusText(GetNode(event
)->FullName(), 1);
711 #endif // wxUSE_STATUSBAR
714 void RegTreeCtrl::OnItemExpanding(wxTreeEvent
& event
)
716 TreeNode
*pNode
= GetNode(event
);
717 bool bExpanding
= event
.GetEventType() == wxEVT_COMMAND_TREE_ITEM_EXPANDING
;
719 // expansion might take some time
720 wxSetCursor(*wxHOURGLASS_CURSOR
);
721 wxLogStatus(wxT("Working..."));
722 wxYield(); // to give the status line a chance to refresh itself
723 m_restoreStatus
= true; // some time later...
725 if ( pNode
->IsKey() )
729 // expanding: add subkeys/values
730 if ( !pNode
->OnExpand() )
735 // collapsing: clean up
741 void RegTreeCtrl::OnBeginEdit(wxTreeEvent
& event
)
743 TreeNode
*pNode
= GetNode(event
);
744 if ( pNode
->IsRoot() || pNode
->Parent()->IsRoot() )
746 wxLogStatus(wxT("This registry key can't be renamed."));
752 m_nameOld
= pNode
->m_strName
;
756 void RegTreeCtrl::OnEndEdit(wxTreeEvent
& event
)
760 wxString name
= event
.GetLabel();
762 TreeNode
*pNode
= GetNode(event
);
763 if ( pNode
->IsKey() )
765 wxRegKey
& key
= pNode
->Key();
766 ok
= key
.Rename(name
);
770 pNode
= pNode
->Parent();
771 wxRegKey
& key
= pNode
->Key();
773 ok
= key
.RenameValue(m_nameOld
, name
);
778 wxLogError(wxT("Failed to rename '%s' to '%s'."),
779 m_nameOld
.c_str(), name
.c_str());
781 #if 0 // MSW tree ctrl doesn't like this at all, it hangs
789 void RegTreeCtrl::OnBeginDrag(wxTreeEvent
& event
)
791 m_copyOnDrop
= event
.GetEventType() == wxEVT_COMMAND_TREE_BEGIN_DRAG
;
793 TreeNode
*pNode
= GetNode(event
);
794 if ( pNode
->IsRoot() || pNode
->Parent()->IsRoot() )
796 wxLogStatus(wxT("This registry key can't be %s."),
797 m_copyOnDrop
? wxT("copied") : wxT("moved"));
801 wxLogStatus(wxT("%s item %s..."),
802 m_copyOnDrop
? wxT("Copying") : wxT("Moving"),
805 m_draggedItem
= pNode
;
811 void RegTreeCtrl::OnEndDrag(wxTreeEvent
& event
)
813 wxCHECK_RET( m_draggedItem
, wxT("end drag without begin drag?") );
815 // clear the pointer anyhow
816 TreeNode
*src
= m_draggedItem
;
817 m_draggedItem
= NULL
;
819 // where are we going to drop it?
820 TreeNode
*dst
= GetNode(event
);
821 if ( dst
&& !dst
->IsKey() )
823 // we need a parent key
827 if ( !dst
|| dst
->IsRoot() )
829 wxLogError(wxT("Can't create a key here."));
834 bool isKey
= src
->IsKey();
835 if ( (isKey
&& (src
== dst
)) ||
836 (!isKey
&& (dst
->Parent() == src
)) ) {
837 wxLogStatus(wxT("Can't copy something on itself"));
842 // remove the "Registry Root\\" from the full name
843 wxString nameSrc
, nameDst
;
844 nameSrc
<< wxString(src
->FullName()).AfterFirst('\\');
845 nameDst
<< wxString(dst
->FullName()).AfterFirst('\\') << '\\'
846 << wxString(src
->FullName()).AfterLast('\\');
848 wxString verb
= m_copyOnDrop
? wxT("copy") : wxT("move");
849 wxString what
= isKey
? wxT("key") : wxT("value");
851 if ( wxMessageBox(wxString::Format
853 wxT("Do you really want to %s the %s %s to %s?"),
859 wxT("RegTest Confirm"),
860 wxICON_QUESTION
| wxYES_NO
| wxCANCEL
, this) != wxYES
) {
867 wxRegKey
& key
= src
->Key();
868 wxRegKey
keyDst(dst
->Key(), src
->m_strName
);
869 ok
= keyDst
.Create(false);
872 wxLogError(wxT("Key '%s' already exists"), keyDst
.GetName().c_str());
876 ok
= key
.Copy(keyDst
);
879 if ( ok
&& !m_copyOnDrop
)
881 // delete the old key
882 ok
= key
.DeleteSelf();
885 src
->Parent()->Refresh();
891 wxRegKey
& key
= src
->Parent()->Key();
892 ok
= key
.CopyValue(src
->m_strName
, dst
->Key());
893 if ( ok
&& !m_copyOnDrop
)
895 // we moved it, so delete the old one
896 ok
= key
.DeleteValue(src
->m_strName
);
902 wxLogError(wxT("Failed to %s registry %s."),
903 verb
.c_str(), what
.c_str());
911 // ----------------------------------------------------------------------------
912 // TreeNode implementation
913 // ----------------------------------------------------------------------------
914 bool RegTreeCtrl::TreeNode::OnExpand()
916 // we add children only once
917 if ( !m_aChildren
.IsEmpty() )
919 // we've been already expanded
925 // we're the root key
926 m_pTree
->AddStdKeys();
930 if ( Parent()->IsRoot() )
932 // we're a standard key
933 m_pKey
= new wxRegKey(m_strName
);
937 // we're a normal key
938 m_pKey
= new wxRegKey(*(Parent()->m_pKey
), m_strName
);
941 if ( !m_pKey
->Open() )
943 wxLogError(wxT("The key '%s' can't be opened."), FullName());
947 // if we're empty, we shouldn't be expandable at all
950 // enumeration variables
955 // enumerate all subkeys
956 bCont
= m_pKey
->GetFirstKey(str
, l
);
959 m_pTree
->InsertNewTreeNode(this, str
, RegImageList::ClosedKey
);
960 bCont
= m_pKey
->GetNextKey(str
, l
);
962 // we have at least this key...
966 // enumerate all values
967 bCont
= m_pKey
->GetFirstValue(str
, l
);
972 strItem
= wxT("<default>");
975 strItem
+= wxT(" = ");
977 // determine the appropriate icon
978 RegImageList::Icon icon
;
979 switch ( m_pKey
->GetValueType(str
) )
981 case wxRegKey::Type_String
:
982 case wxRegKey::Type_Expand_String
:
983 case wxRegKey::Type_Multi_String
:
986 icon
= RegImageList::TextValue
;
987 m_pKey
->QueryValue(str
, strValue
);
992 case wxRegKey::Type_None
:
993 // @@ handle the error...
994 icon
= RegImageList::BinaryValue
;
997 case wxRegKey::Type_Dword
:
1000 m_pKey
->QueryValue(str
, &l
);
1007 icon
= RegImageList::BinaryValue
;
1010 m_pTree
->InsertNewTreeNode(this, str
, icon
, &strItem
);
1011 bCont
= m_pKey
->GetNextValue(str
, l
);
1013 // we have at least this value...
1019 // this is for the case when our last child was just deleted
1020 wxTreeItemId
theId(Id()); // Temp variable seems necessary for BC++
1021 m_pTree
->Collapse(theId
);
1023 // we won't be expanded any more
1024 m_pTree
->SetItemHasChildren(theId
, false);
1030 void RegTreeCtrl::TreeNode::OnCollapse()
1037 void RegTreeCtrl::TreeNode::Refresh()
1042 wxTreeItemId
theId(Id()); // Temp variable seems necessary for BC++
1043 bool wasExpanded
= m_pTree
->IsExpanded(theId
);
1045 m_pTree
->Collapse(theId
);
1048 m_pTree
->SetItemHasChildren(theId
);
1051 m_pTree
->Expand(theId
);
1056 bool RegTreeCtrl::TreeNode::DeleteChild(TreeNode
*child
)
1058 int index
= m_aChildren
.Index(child
);
1059 wxCHECK_MSG( index
!= wxNOT_FOUND
, false,
1060 wxT("our child in tree should be in m_aChildren") );
1062 m_aChildren
.RemoveAt((size_t)index
);
1065 if ( child
->IsKey() )
1067 // must close key before deleting it
1068 child
->OnCollapse();
1070 ok
= Key().DeleteKey(child
->m_strName
);
1074 ok
= Key().DeleteValue(child
->m_strName
);
1079 wxTreeItemId
theId(child
->Id()); // Temp variable seems necessary for BC++
1080 m_pTree
->Delete(theId
);
1088 void RegTreeCtrl::TreeNode::DestroyChildren()
1090 // destroy all children
1091 size_t nCount
= m_aChildren
.GetCount();
1092 for ( size_t n
= 0; n
< nCount
; n
++ )
1094 wxTreeItemId lId
= m_aChildren
[n
]->Id();
1095 m_pTree
->Delete(lId
);
1098 m_aChildren
.Empty();
1101 RegTreeCtrl::TreeNode::~TreeNode()
1106 const wxChar
*RegTreeCtrl::TreeNode::FullName() const
1108 static wxString s_strName
;
1112 return wxT("Registry Root");
1116 // our own registry key might not (yet) exist or we might be a value,
1117 // so just use the parent's and concatenate
1118 s_strName
= Parent()->FullName();
1119 s_strName
<< wxT('\\') << m_strName
;
1125 // ----------------------------------------------------------------------------
1126 // operations on RegTreeCtrl
1127 // ----------------------------------------------------------------------------
1129 void RegTreeCtrl::GoTo(const wxString
& location
)
1131 wxStringTokenizer
tk(location
, wxT("\\"));
1133 wxTreeItemId id
= GetRootItem();
1135 while ( tk
.HasMoreTokens() )
1137 wxString subkey
= tk
.GetNextToken();
1139 wxTreeItemId idCurrent
= id
;
1140 if ( !IsExpanded(idCurrent
) )
1143 wxTreeItemIdValue dummy
;
1144 id
= GetFirstChild(idCurrent
, dummy
);
1146 if ( idCurrent
== GetRootItem() )
1148 // special case: we understand both HKCU and HKEY_CURRENT_USER here
1149 for ( size_t key
= 0; key
< wxRegKey::nStdKeys
; key
++ )
1151 if ( subkey
== wxRegKey::GetStdKeyName(key
)
1152 || subkey
== wxRegKey::GetStdKeyShortName(key
) )
1157 id
= GetNextChild(idCurrent
, dummy
);
1162 // enum all children
1165 if ( subkey
== ((TreeNode
*)GetItemData(id
))->m_strName
)
1168 id
= GetNextChild(idCurrent
, dummy
);
1174 wxLogError(wxT("No such key '%s'."), location
.c_str());
1184 void RegTreeCtrl::DeleteSelected()
1186 wxTreeItemId lCurrent
= GetSelection(),
1187 lParent
= GetItemParent(lCurrent
);
1189 if ( lParent
== GetRootItem() )
1191 wxLogError(wxT("Can't delete root key."));
1195 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
),
1196 *pParent
= (TreeNode
*)GetItemData(lParent
);
1198 wxCHECK_RET(pCurrent
&& pParent
, wxT("either node or parent without data?"));
1200 if ( pParent
->IsRoot() )
1202 wxLogError(wxT("Can't delete standard key."));
1206 wxString what
= pCurrent
->IsKey() ? wxT("key") : wxT("value");
1207 if ( wxMessageBox(wxString::Format
1209 wxT("Do you really want to delete this %s?"),
1212 wxT("Confirmation"),
1213 wxICON_QUESTION
| wxYES_NO
| wxCANCEL
, this) != wxYES
)
1218 pParent
->DeleteChild(pCurrent
);
1221 void RegTreeCtrl::CreateNewKey(const wxString
& strName
)
1223 wxTreeItemId lCurrent
= GetSelection();
1224 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1226 wxCHECK_RET( pCurrent
!= NULL
, wxT("node without data?") );
1228 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
1230 if ( pCurrent
->IsRoot() )
1232 wxLogError(wxT("Can't create a new key under the root key."));
1236 wxRegKey
key(pCurrent
->Key(), strName
);
1238 pCurrent
->Refresh();
1241 void RegTreeCtrl::CreateNewTextValue(const wxString
& strName
)
1243 wxTreeItemId lCurrent
= GetSelection();
1244 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1246 wxCHECK_RET( pCurrent
!= NULL
, wxT("node without data?") );
1248 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
1250 if ( pCurrent
->IsRoot() )
1252 wxLogError(wxT("Can't create a new value under the root key."));
1256 if ( pCurrent
->Key().SetValue(strName
, wxEmptyString
) )
1257 pCurrent
->Refresh();
1260 void RegTreeCtrl::CreateNewBinaryValue(const wxString
& strName
)
1262 wxTreeItemId lCurrent
= GetSelection();
1263 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1265 wxCHECK_RET( pCurrent
!= NULL
, wxT("node without data?") );
1267 wxASSERT( pCurrent
->IsKey() ); // check must have been done before
1269 if ( pCurrent
->IsRoot() )
1271 wxLogError(wxT("Can't create a new value under the root key."));
1275 if ( pCurrent
->Key().SetValue(strName
, 0) )
1276 pCurrent
->Refresh();
1279 void RegTreeCtrl::ShowProperties()
1281 wxTreeItemId lCurrent
= GetSelection();
1282 TreeNode
*pCurrent
= (TreeNode
*)GetItemData(lCurrent
);
1284 if ( !pCurrent
|| pCurrent
->IsRoot() )
1286 wxLogStatus(wxT("No properties"));
1291 if ( pCurrent
->IsKey() )
1293 const wxRegKey
& key
= pCurrent
->Key();
1294 size_t nSubKeys
, nValues
;
1295 if ( !key
.GetKeyInfo(&nSubKeys
, NULL
, &nValues
, NULL
) )
1297 wxLogError(wxT("Couldn't get key info"));
1301 wxLogMessage(wxT("Key '%s' has %u subkeys and %u values."),
1302 key
.GetName().c_str(), nSubKeys
, nValues
);
1305 else // it's a value
1307 TreeNode
*parent
= pCurrent
->Parent();
1308 wxCHECK_RET( parent
, wxT("reg value without key?") );
1310 const wxRegKey
& key
= parent
->Key();
1311 const wxChar
*value
= pCurrent
->m_strName
.c_str();
1312 wxLogMessage(wxT("Value '%s' under the key '%s' is of type ")
1315 parent
->m_strName
.c_str(),
1316 key
.GetValueType(value
),
1317 key
.IsNumericValue(value
) ? wxT("numeric") : wxT("string"));
1322 bool RegTreeCtrl::IsKeySelected() const
1324 wxTreeItemId lCurrent
= GetSelection();
1325 TreeNode
*pCurrent
= (TreeNode
*) GetItemData(lCurrent
);
1327 wxCHECK( pCurrent
!= NULL
, false );
1329 return pCurrent
->IsKey();
1332 void RegTreeCtrl::DoRefresh()
1334 wxTreeItemId lId
= GetSelection();
1338 TreeNode
*pNode
= (TreeNode
*) GetItemData(lId
);
1340 wxCHECK_RET( pNode
!= NULL
, wxT("tree item without data?") );