1/* 2 * Copyright 2004-2011 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, <kallisti5@unixzen.com> 7 */ 8 9 10#include "NetworkSetupWindow.h" 11 12#include <Application.h> 13#include <Catalog.h> 14#include <GroupLayout.h> 15#include <GroupLayoutBuilder.h> 16#include <InterfaceKit.h> 17#include <Locale.h> 18#include <Roster.h> 19#include <StorageKit.h> 20#include <SupportKit.h> 21#include <TabView.h> 22 23#include <stdio.h> 24#include <string.h> 25#include <stdlib.h> 26 27 28#undef B_TRANSLATION_CONTEXT 29#define B_TRANSLATION_CONTEXT "NetworkSetupWindow" 30 31 32// -------------------------------------------------------------- 33NetworkSetupWindow::NetworkSetupWindow(const char *title) 34 : 35 BWindow(BRect(100, 100, 300, 300), title, B_TITLED_WINDOW, 36 B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS), 37 fAddonCount(0) 38{ 39 // ---- Profiles section 40 BMenu *profilesPopup = new BPopUpMenu("<none>"); 41 _BuildProfilesMenu(profilesPopup, kMsgProfileSelected); 42 43 BMenuField *profilesMenuField = new BMenuField("profiles_menu", 44 B_TRANSLATE("Profile:"), profilesPopup); 45 46 profilesMenuField->SetFont(be_bold_font); 47 profilesMenuField->SetEnabled(false); 48 49 // ---- Settings section 50 51 fPanel = new BTabView("showview_box"); 52 53 // ---- Bottom globals buttons section 54 BBox *bottomDivider = new BBox(B_EMPTY_STRING); 55 bottomDivider->SetBorder(B_PLAIN_BORDER); 56 57 fApplyButton = new BButton("apply", B_TRANSLATE("Apply"), 58 new BMessage(kMsgApply)); 59 60 fRevertButton = new BButton("revert", B_TRANSLATE("Revert"), 61 new BMessage(kMsgRevert)); 62 // fRevertButton->SetEnabled(false); 63 64 // Enable boxes resizing modes 65 fPanel->SetResizingMode(B_FOLLOW_ALL); 66 67 // Build the layout 68 SetLayout(new BGroupLayout(B_VERTICAL)); 69 70 AddChild(BGroupLayoutBuilder(B_VERTICAL, 10) 71 .AddGroup(B_HORIZONTAL, 5) 72 .Add(profilesMenuField) 73 .AddGlue() 74 .End() 75 .Add(fPanel) 76 .Add(bottomDivider) 77 .AddGroup(B_HORIZONTAL, 5) 78 .AddGlue() 79 .Add(fRevertButton) 80 .Add(fApplyButton) 81 .End() 82 .SetInsets(10, 10, 10, 10) 83 ); 84 85 _BuildShowTabView(kMsgAddonShow); 86 87 bottomDivider->SetExplicitMaxSize(BSize(B_SIZE_UNSET, 1)); 88 fPanel->SetExplicitMinSize(BSize(fMinAddonViewRect.Width(), 89 fMinAddonViewRect.Height())); 90 91 fAddonView = NULL; 92 93} 94 95 96NetworkSetupWindow::~NetworkSetupWindow() 97{ 98} 99 100 101bool 102NetworkSetupWindow::QuitRequested() 103{ 104 be_app->PostMessage(B_QUIT_REQUESTED); 105 return true; 106} 107 108 109void 110NetworkSetupWindow::MessageReceived(BMessage* msg) 111{ 112 switch (msg->what) { 113 case kMsgProfileNew: 114 break; 115 116 case kMsgProfileSelected: { 117 BPath name; 118 const char *path; 119 bool is_default; 120 bool is_current; 121 122 if (msg->FindString("path", &path) != B_OK) 123 break; 124 125 name.SetTo(path); 126 127 is_default = (strcmp(name.Leaf(), "default") == 0); 128 is_current = (strcmp(name.Leaf(), "current") == 0); 129 130 fApplyButton->SetEnabled(!is_current); 131 break; 132 } 133 134 case kMsgRevert: { 135 for (int addonIndex = 0; addonIndex < fAddonCount; addonIndex++) { 136 NetworkSetupAddOn* addon 137 = fNetworkAddOnMap[addonIndex]; 138 addon->Revert(); 139 } 140 break; 141 } 142 143 144 case kMsgApply: { 145 for (int addonIndex = 0; addonIndex < fAddonCount; addonIndex++) { 146 NetworkSetupAddOn* addon 147 = fNetworkAddOnMap[addonIndex]; 148 addon->Save(); 149 } 150 break; 151 } 152 153 case kMsgAddonShow: { 154 if (fAddonView) 155 fAddonView->RemoveSelf(); 156 157 fAddonView = NULL; 158 if (msg->FindPointer("addon_view", (void **) &fAddonView) != B_OK) 159 break; 160 161 fPanel->AddChild(fAddonView); 162 fAddonView->ResizeTo(fPanel->Bounds().Width(), 163 fPanel->Bounds().Height()); 164 break; 165 } 166 167 default: 168 inherited::MessageReceived(msg); 169 } 170} 171 172 173void 174NetworkSetupWindow::_BuildProfilesMenu(BMenu* menu, int32 msg_what) 175{ 176 BMenuItem* item; 177 char current_profile[256] = { 0 }; 178 179 menu->SetRadioMode(true); 180 181 BDirectory dir("/boot/common/settings/network/profiles"); 182 183 if (dir.InitCheck() == B_OK) { 184 BEntry entry; 185 BMessage* msg; 186 187 dir.Rewind(); 188 while (dir.GetNextEntry(&entry) >= 0) { 189 BPath name; 190 entry.GetPath(&name); 191 192 if (entry.IsSymLink() && 193 strcmp("current", name.Leaf()) == 0) { 194 BSymLink symlink(&entry); 195 196 if (symlink.IsAbsolute()) 197 // oh oh, sorry, wrong symlink... 198 continue; 199 200 symlink.ReadLink(current_profile, sizeof(current_profile)); 201 continue; 202 }; 203 204 if (!entry.IsDirectory()) 205 continue; 206 207 msg = new BMessage(msg_what); 208 msg->AddString("path", name.Path()); 209 210 item = new BMenuItem(name.Leaf(), msg); 211 menu->AddItem(item); 212 } 213 } 214 215 menu->AddSeparatorItem(); 216 menu->AddItem(new BMenuItem(B_TRANSLATE("New" B_UTF8_ELLIPSIS), 217 new BMessage(kMsgProfileNew))); 218 menu->AddItem(new BMenuItem(B_TRANSLATE("Manage" B_UTF8_ELLIPSIS), 219 new BMessage(kMsgProfileManage))); 220 221 if (strlen(current_profile)) { 222 item = menu->FindItem(current_profile); 223 if (item) { 224 BString label; 225 label << item->Label(); 226 label << " (current)"; 227 item->SetLabel(label.String()); 228 item->SetMarked(true); 229 } 230 } 231} 232 233 234void 235NetworkSetupWindow::_BuildShowTabView(int32 msg_what) 236{ 237 BPath path; 238 BPath addon_path; 239 BDirectory dir; 240 BEntry entry; 241 242 char* search_paths = getenv("ADDON_PATH"); 243 if (!search_paths) 244 return; 245 246 fMinAddonViewRect.Set(0, 0, 375, 225); // Minimum size 247 248 search_paths = strdup(search_paths); 249 char* next_path_token; 250 char* search_path = strtok_r(search_paths, ":", &next_path_token); 251 252 while (search_path) { 253 if (strncmp(search_path, "%A/", 3) == 0) { 254 app_info ai; 255 be_app->GetAppInfo(&ai); 256 entry.SetTo(&ai.ref); 257 entry.GetPath(&path); 258 path.GetParent(&path); 259 path.Append(search_path + 3); 260 } else { 261 path.SetTo(search_path); 262 path.Append("Network Setup"); 263 } 264 265 search_path = strtok_r(NULL, ":", &next_path_token); 266 267 dir.SetTo(path.Path()); 268 if (dir.InitCheck() != B_OK) 269 continue; 270 271 dir.Rewind(); 272 while (dir.GetNextEntry(&entry) >= 0) { 273 if (entry.IsDirectory()) 274 continue; 275 276 entry.GetPath(&addon_path); 277 image_id addon_id = load_add_on(addon_path.Path()); 278 if (addon_id < 0) { 279 printf("Failed to load %s addon: %s.\n", addon_path.Path(), 280 strerror(addon_id)); 281 continue; 282 } 283 284 network_setup_addon_instantiate get_nth_addon; 285 status_t status = get_image_symbol(addon_id, "get_nth_addon", 286 B_SYMBOL_TYPE_TEXT, (void **) &get_nth_addon); 287 288 int tabCount = 0; 289 290 if (status == B_OK) { 291 while ((fNetworkAddOnMap[fAddonCount] 292 = get_nth_addon(addon_id, tabCount)) != NULL) { 293 printf("Adding Tab: %d\n", fAddonCount); 294 BMessage* msg = new BMessage(msg_what); 295 296 BRect r(0, 0, 0, 0); 297 BView* addon_view 298 = fNetworkAddOnMap[fAddonCount]->CreateView(&r); 299 fMinAddonViewRect = fMinAddonViewRect | r; 300 301 msg->AddInt32("image_id", addon_id); 302 msg->AddString("addon_path", addon_path.Path()); 303 msg->AddPointer("addon", fNetworkAddOnMap[fAddonCount]); 304 msg->AddPointer("addon_view", addon_view); 305 306 BTab *tab = new BTab; 307 fPanel->AddTab(addon_view, tab); 308 tab->SetLabel(fNetworkAddOnMap[fAddonCount]->Name()); 309 fAddonCount++; 310 // Number of tab addons total 311 tabCount++; 312 // Tabs for *this* addon 313 } 314 continue; 315 } 316 317 // No "addon instantiate function" symbol found in this addon 318 printf("No symbol \"get_nth_addon\" found in %s addon: not a " 319 "network setup addon!\n", addon_path.Path()); 320 unload_add_on(addon_id); 321 } 322 } 323 324 free(search_paths); 325} 326