]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/pk3man/tree.cpp
* added pk3man and fixed it to compile for latest radiant
[xonotic/netradiant.git] / contrib / pk3man / tree.cpp
1 // tree.cpp: implementation of the CTree class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #include "stdafx.h"
6 #include "tree.h"
7 #include <string>
8 #include "mainwnd.h"
9
10 extern CMainWnd *g_pMainWnd;
11
12
13 static void button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
14 {
15         if (event->button==3)
16                 g_pMainWnd->HandleDrop();
17 }
18
19 //////////////////////////////////////////////////////////////////////
20 // Construction/Destruction
21 //////////////////////////////////////////////////////////////////////
22
23 CTree::CTree()
24 {
25         m_Tree=NULL;
26         m_Root=NULL;
27
28 }
29
30 CTree::~CTree()
31 {
32
33 }
34
35 void CTree::Init(GtkWidget *win)
36 {
37         m_pMainWnd=win;
38
39         // create the tree
40         m_Tree=gtk_tree_new();
41
42         // Add tree to passed scroll window
43         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(win),(GtkWidget*)m_Tree);
44
45         // Show it
46         gtk_widget_show(m_Tree);
47
48         // connect signal
49         gtk_signal_connect (GTK_OBJECT(m_Tree), "select_child",
50                                 GTK_SIGNAL_FUNC(cb_select_child), m_Tree);
51
52         // create the root item
53         GtkWidget *item=gtk_tree_item_new_with_label("root");
54         gtk_tree_append(GTK_TREE(m_Tree),item);
55         gtk_widget_show(item);
56
57         gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL);
58
59         m_Root=gtk_tree_new();
60         gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),m_Root);
61         gtk_tree_item_expand(GTK_TREE_ITEM(item));
62
63
64         // connect signal
65         gtk_signal_connect (GTK_OBJECT(m_Root), "select_child",
66                                 GTK_SIGNAL_FUNC(cb_select_child), m_Tree);
67
68         // ok were done
69         return;
70 }
71
72 void CTree::Clear()
73 {
74         gtk_widget_destroy(m_Tree);
75         Init(m_pMainWnd);
76 }
77
78 void CTree::AddPath(const char *buff)
79 {
80         Str path(buff);
81
82         // convert '\' to '/'
83         for (int c=0 ; c<path.GetLength() ; c++)
84         {
85                 if (path.GetAt(c)=='\\')
86                         path.SetAt(c,'/');
87         }
88
89         if (path[0]=='/')
90                 path=path.Mid(1);
91
92         // lets tokenize it first
93         if (path.GetAt(path.GetLength()-1)=='/')
94         {
95                 // its just a folder path, no file
96                 return;
97         }
98
99         GtkWidget *node=m_Root;
100
101         long pos=path.Find('/');
102         while (pos!=-1)
103         {
104                 Str folder=path.Left(pos);
105                 path=path.Mid(pos+1);
106
107                 // add a folder, or retrieve its node if it already exists
108                 node=AddFolder(folder.GetBuffer(),node);
109
110                 pos=path.Find('/');
111         }
112
113         // add the filename to the final nested node
114         AddFile(path.GetBuffer(),node);
115 }
116
117
118 void CTree::AddFile(const char *buff, GtkWidget *node)
119 {
120         Str file(buff);
121
122         if (node==NULL)
123                 node=m_Root;
124
125         GtkWidget *item=gtk_tree_item_new_with_label(buff);
126         gtk_tree_append(GTK_TREE(node),item);
127         gtk_widget_show(item);
128
129         gtk_widget_set_name(item,file);
130
131         //      gtk_signal_connect (GTK_OBJECT(item), "select_child",
132         //                      GTK_SIGNAL_FUNC(cb_select_child), item);
133
134         gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL);
135
136
137         // a file is the last item in the tree so no tree is needed
138 }
139
140 GtkWidget* CTree::AddFolder(const char *buff,GtkWidget *node)
141 {
142         Str folder(buff);
143
144         if (node==NULL)
145                 node=m_Root;
146
147         // search the node's siblings for the folder
148         GList *children = gtk_container_children (GTK_CONTAINER (node));
149     while (children)
150         {
151                 GtkTreeItem *tree_item=(GTK_TREE_ITEM (children->data));
152
153                 // check item for equality with the folder
154                 // and weather it has a tree attached
155
156                 if (GTK_TREE_ITEM_SUBTREE(tree_item))
157                 {
158                         GtkItem *item=GTK_ITEM(tree_item);
159
160                         GList *item_children=gtk_container_children(GTK_CONTAINER(item));
161
162                         GtkLabel *label=GTK_LABEL(item_children->data);
163
164                         if (strcmp(label->label,buff)==0)
165                         {
166                                 g_list_free(item_children);
167                                 g_list_free(children);
168
169                                 // return tree attached to the item
170                                 return GTK_TREE_ITEM_SUBTREE(tree_item);
171                         }
172
173                         g_list_free(item_children);
174                 }
175
176                 children = g_list_remove_link (children, children);
177         }
178
179         g_list_free(children);
180
181         // ok, not found so we add it
182         GtkWidget *item=gtk_tree_item_new_with_label(buff);
183         gtk_tree_append(GTK_TREE(node),item);
184         gtk_widget_show(item);
185
186         GtkWidget *tree=gtk_tree_new();
187         gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),tree);
188         gtk_widget_set_name(tree,buff);
189
190         gtk_signal_connect (GTK_OBJECT(tree), "select_child",
191                       GTK_SIGNAL_FUNC(cb_select_child), tree);
192
193         gtk_signal_connect (GTK_OBJECT (item), "button_release_event",GTK_SIGNAL_FUNC (button_release), NULL);
194
195
196         //gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
197       //                GTK_SIGNAL_FUNC(cb_selection_changed), tree, this);
198
199         return tree;
200 }
201
202
203 std::string CTree::GetFullPath(GtkWidget *child)
204 {
205         std::string path;
206         gchar *name;
207
208         GtkLabel *label = GTK_LABEL (GTK_BIN (child)->child);
209         gtk_label_get (label, &name);
210         path=name;
211
212         if (path.compare("root")==0)
213                 return "root";
214
215         while (1)
216         {
217                 // this gets an items parent tree
218                 GtkWidget *tr=(child->parent);
219
220                 if (GTK_WIDGET(tr)==m_Root)
221                         break;
222
223                 // and now its item
224                 child=GTK_TREE(tr)->tree_owner;
225
226                 // and now the items label
227                 label = GTK_LABEL (GTK_BIN (child)->child);
228                 gtk_label_get (label, &name);
229                 std::string lbl=name;
230                 path=lbl+"/"+path;
231         }
232
233         return path;
234 }
235
236 void CTree::RemovePath(const char *path)
237 {
238         // not used yet
239 }
240
241
242 void CTree::SelectChild(GtkWidget *child)
243 {
244         g_pMainWnd->UpdateStatus();
245         g_pMainWnd->UpdateToolBar();
246 }
247
248 void cb_select_child (GtkWidget *root_tree, GtkWidget *child, GtkWidget *subtree)
249 {
250         g_pMainWnd->m_Tree.SelectChild(child);
251 }
252
253
254 std::string CTree::GetSelected()
255 {
256         std::string path="";
257
258         if (!GTK_TREE(m_Tree)->selection)
259                 return path;
260
261         GList *selected = (GTK_TREE(m_Tree)->selection);
262
263         GtkWidget *item=GTK_WIDGET(selected->data);
264
265         if (GTK_TREE_ITEM(item)->subtree)
266                 return path;
267
268         path=GetFullPath(item);
269
270         return path;
271 }