1 /* 2 * Copyright 2003-2004 Waldemar Kornewald. All rights reserved. 3 * Copyright 2017 Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "DialUpView.h" 9 #include "DialUpAddon.h" 10 11 #include <cstring> 12 #include "InterfaceUtils.h" 13 #include "MessageDriverSettingsUtils.h" 14 #include "TextRequestDialog.h" 15 16 // built-in add-ons 17 #include "ConnectionOptionsAddon.h" 18 #include "GeneralAddon.h" 19 #include "IPCPAddon.h" 20 #include "PPPoEAddon.h" 21 22 #include <PPPInterface.h> 23 #include <settings_tools.h> 24 #include <TemplateList.h> 25 26 #include <Application.h> 27 28 #include <Alert.h> 29 #include <Button.h> 30 #include <MenuField.h> 31 #include <MenuItem.h> 32 #include <Messenger.h> 33 #include <PopUpMenu.h> 34 #include <LayoutBuilder.h> 35 #include <StringView.h> 36 #include <TabView.h> 37 38 #include <Directory.h> 39 #include <Entry.h> 40 #include <File.h> 41 #include <Path.h> 42 43 44 // message constants 45 static const uint32 kMsgCreateNew = 'NEWI'; 46 static const uint32 kMsgFinishCreateNew = 'FNEW'; 47 static const uint32 kMsgDeleteCurrent = 'DELI'; 48 static const uint32 kMsgSelectInterface = 'SELI'; 49 static const uint32 kMsgConnectButton = 'CONI'; 50 51 // labels 52 static const char *kLabelInterface = "Interface: "; 53 static const char *kLabelInterfaceName = "Interface Name: "; 54 static const char *kLabelCreateNewInterface = "Create New Interface"; 55 static const char *kLabelCreateNew = "Create New..."; 56 static const char *kLabelDeleteCurrent = "Delete Current"; 57 static const char *kLabelConnect = "Connect"; 58 static const char *kLabelDisconnect = "Disconnect"; 59 static const char *kLabelOK = "OK"; 60 61 // connection status strings 62 static const char *kTextConnecting = "Connecting..."; 63 static const char *kTextConnectionEstablished = "Connection established."; 64 static const char *kTextNotConnected = "Not connected."; 65 static const char *kTextDeviceUpFailed = "Failed to connect."; 66 static const char *kTextAuthenticating = "Authenticating..."; 67 static const char *kTextAuthenticationFailed = "Authentication failed!"; 68 static const char *kTextConnectionLost = "Connection lost!"; 69 static const char *kTextCreationError = "Error creating interface!"; 70 static const char *kTextNoInterfacesFound = "Please create a new interface..."; 71 static const char *kTextChooseInterfaceName = "Please choose a new name for this " 72 "interface."; 73 74 // error strings for alerts 75 static const char *kErrorTitle = "Error"; 76 static const char *kErrorNoPPPStack = "Error: Could not access the PPP stack!"; 77 static const char *kErrorInterfaceExists = "Error: An interface with this name " 78 "already exists!"; 79 static const char *kErrorLoadingFailed = "Error: Failed loading interface! The " 80 "current settings will be deleted."; 81 static const char *kErrorSavingFailed = "Error: Failed saving interface settings!"; 82 83 84 static 85 status_t 86 up_down_thread(void *data) 87 { 88 static_cast<DialUpView*>(data)->UpDownThread(); 89 return B_OK; 90 } 91 92 93 DialUpView::DialUpView() 94 : BView("DialUpView", 0), 95 fListener(this), 96 fUpDownThread(-1), 97 fDriverSettings(NULL), 98 fCurrentItem(NULL), 99 fWatching(PPP_UNDEFINED_INTERFACE_ID), 100 fKeepLabel(false) 101 { 102 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 103 104 // add messenger to us so add-ons can contact us 105 BMessenger messenger(this); 106 fAddons.AddMessenger(DUN_MESSENGER, messenger); 107 108 // create pop-up with all interfaces and "New..."/"Delete current" items 109 fInterfaceMenu = new BPopUpMenu(kLabelCreateNew); 110 fMenuField = new BMenuField("Interfaces", kLabelInterface, fInterfaceMenu); 111 112 fTabView = new BTabView("TabView", B_WIDTH_FROM_LABEL); 113 BRect tabViewRect(fTabView->Bounds()); 114 fAddons.AddRect(DUN_TAB_VIEW_RECT, tabViewRect); // FIXME: remove 115 116 fStringView = new BStringView("NoInterfacesFound", 117 kTextNoInterfacesFound); 118 fStringView->SetAlignment(B_ALIGN_CENTER); 119 fStringView->Hide(); 120 fCreateNewButton = new BButton("CreateNewButton", 121 kLabelCreateNewInterface, new BMessage(kMsgCreateNew)); 122 fCreateNewButton->Hide(); 123 124 fStatusView = new BStringView("StatusView", kTextNotConnected); 125 126 fConnectButton = new BButton("ConnectButton", kLabelConnect, 127 new BMessage(kMsgConnectButton)); 128 129 BLayoutBuilder::Group<>(this, B_VERTICAL) 130 .Add(fMenuField) 131 .Add(fTabView) 132 .Add(fStringView) 133 .Add(fCreateNewButton) 134 .AddGroup(B_HORIZONTAL) 135 .Add(fStatusView) 136 .AddGlue() 137 .Add(fConnectButton) 138 .End() 139 .End(); 140 141 // initialize 142 LoadInterfaces(); 143 LoadAddons(); 144 CreateTabs(); 145 fCurrentItem = NULL; 146 // reset, otherwise SelectInterface will not load the settings 147 SelectInterface(0); 148 UpdateControls(); 149 } 150 151 152 DialUpView::~DialUpView() 153 { 154 SaveSettingsToFile(); 155 156 int32 tmp; 157 wait_for_thread(fUpDownThread, &tmp); 158 159 // free known add-on types (these should free their known add-on types, etc.) 160 DialUpAddon *addon; 161 for(int32 index = 0; 162 fAddons.FindPointer(DUN_DELETE_ON_QUIT, index, 163 reinterpret_cast<void**>(&addon)) == B_OK; 164 index++) 165 delete addon; 166 } 167 168 169 void 170 DialUpView::AttachedToWindow() 171 { 172 fInterfaceMenu->SetTargetForItems(this); 173 fCreateNewButton->SetTarget(this); 174 fConnectButton->SetTarget(this); 175 176 if(fListener.InitCheck() != B_OK) { 177 (new BAlert(kErrorTitle, kErrorNoPPPStack, kLabelOK, 178 NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL); 179 fConnectButton->Hide(); 180 } 181 } 182 183 184 void 185 DialUpView::MessageReceived(BMessage *message) 186 { 187 switch(message->what) { 188 case PPP_REPORT_MESSAGE: 189 HandleReportMessage(message); 190 break; 191 192 // ------------------------------------------------- 193 case kMsgCreateNew: { 194 (new TextRequestDialog(kLabelCreateNewInterface, kTextChooseInterfaceName, 195 kLabelInterfaceName))->Go( 196 new BInvoker(new BMessage(kMsgFinishCreateNew), this)); 197 } break; 198 199 case kMsgFinishCreateNew: { 200 int32 which; 201 message->FindInt32("which", &which); 202 const char *name = message->FindString("text"); 203 if(which == 1 && name && strlen(name) > 0) 204 AddInterface(name, true); 205 206 if(fCurrentItem) 207 fCurrentItem->SetMarked(true); 208 } break; 209 // ------------------------------------------------- 210 211 case kMsgDeleteCurrent: { 212 if(!fCurrentItem) 213 return; 214 215 fInterfaceMenu->RemoveItem(fCurrentItem); 216 BDirectory settings, profile; 217 GetPPPDirectories(&settings, &profile); 218 BEntry entry; 219 settings.FindEntry(fCurrentItem->Label(), &entry); 220 entry.Remove(); 221 profile.FindEntry(fCurrentItem->Label(), &entry); 222 entry.Remove(); 223 delete fCurrentItem; 224 fCurrentItem = NULL; 225 226 BMenuItem *marked = fInterfaceMenu->FindMarked(); 227 if(marked) 228 marked->SetMarked(false); 229 230 UpdateControls(); 231 SelectInterface(0); 232 // this stops watching the deleted interface 233 } break; 234 235 case kMsgSelectInterface: { 236 int32 index; 237 message->FindInt32("index", &index); 238 SelectInterface(index); 239 } break; 240 241 case kMsgConnectButton: { 242 if(!fCurrentItem || fUpDownThread != -1) 243 return; 244 245 fUpDownThread = spawn_thread(up_down_thread, "up_down_thread", 246 B_NORMAL_PRIORITY, this); 247 resume_thread(fUpDownThread); 248 } break; 249 250 default: 251 BView::MessageReceived(message); 252 } 253 } 254 255 256 bool 257 DialUpView::SelectInterfaceNamed(const char *name) 258 { 259 BMenuItem *item = fInterfaceMenu->FindItem(name); 260 261 int32 index = fInterfaceMenu->IndexOf(item); 262 if(!item || index >= CountInterfaces()) 263 return false; 264 265 SelectInterface(index); 266 267 return true; 268 } 269 270 271 bool 272 DialUpView::NeedsRequest() const 273 { 274 return fGeneralAddon ? fGeneralAddon->NeedsAuthenticationRequest() : false; 275 } 276 277 278 BView* 279 DialUpView::StatusView() const 280 { 281 return fStatusView; 282 } 283 284 285 BView* 286 DialUpView::ConnectButton() const 287 { 288 return fConnectButton; 289 } 290 291 292 bool 293 DialUpView::LoadSettings(bool isNew) 294 { 295 fSettings.MakeEmpty(); 296 fProfile.MakeEmpty(); 297 BMessage *settingsPointer = fCurrentItem ? &fSettings : NULL, 298 *profilePointer = fCurrentItem ? &fProfile : NULL; 299 300 if(fCurrentItem && !isNew) { 301 BString name("pppidf/"); 302 name << fCurrentItem->Label(); 303 if(!ReadMessageDriverSettings(name.String(), &fSettings)) 304 return false; 305 name = "pppidf/profile/"; 306 name << fCurrentItem->Label(); 307 if(!ReadMessageDriverSettings(name.String(), &fProfile)) 308 profilePointer = settingsPointer; 309 } 310 311 DialUpAddon *addon; 312 for(int32 index = 0; fAddons.FindPointer(DUN_TAB_ADDON_TYPE, index, 313 reinterpret_cast<void**>(&addon)) == B_OK; index++) { 314 if(!addon) 315 continue; 316 317 if(!addon->LoadSettings(settingsPointer, profilePointer, isNew)) 318 return false; 319 } 320 321 // TODO: check if settings are valid 322 323 return true; 324 } 325 326 327 void 328 DialUpView::IsModified(bool *settings, bool *profile) 329 { 330 *settings = *profile = false; 331 bool addonSettingsChanged, addonProfileChanged; 332 // for current addon 333 334 DialUpAddon *addon; 335 for(int32 index = 0; fAddons.FindPointer(DUN_TAB_ADDON_TYPE, index, 336 reinterpret_cast<void**>(&addon)) == B_OK; index++) { 337 if(!addon) 338 continue; 339 340 addon->IsModified(&addonSettingsChanged, &addonProfileChanged); 341 if(addonSettingsChanged) 342 *settings = true; 343 if(addonProfileChanged) 344 *profile = true; 345 } 346 } 347 348 349 bool 350 DialUpView::SaveSettings(BMessage *settings, BMessage *profile, bool saveTemporary) 351 { 352 if(!fCurrentItem || !settings || !profile) 353 return false; 354 355 DialUpAddon *addon; 356 TemplateList<DialUpAddon*> addons; 357 for(int32 index = 0; 358 fAddons.FindPointer(DUN_TAB_ADDON_TYPE, index, 359 reinterpret_cast<void**>(&addon)) == B_OK; index++) { 360 if(!addon) 361 continue; 362 363 int32 insertIndex = 0; 364 for(; insertIndex < addons.CountItems(); insertIndex++) 365 if(addons.ItemAt(insertIndex)->Priority() <= addon->Priority()) 366 break; 367 368 addons.AddItem(addon, insertIndex); 369 } 370 371 settings->AddInt32("Interface", static_cast<int32>(fWatching)); 372 if(fCurrentItem) 373 settings->AddString("InterfaceName", fCurrentItem->Label()); 374 375 for(int32 index = 0; index < addons.CountItems(); index++) 376 if(!addons.ItemAt(index)->SaveSettings(settings, profile, saveTemporary)) 377 return false; 378 379 return true; 380 } 381 382 383 bool 384 DialUpView::SaveSettingsToFile() 385 { 386 bool settingsChanged, profileChanged; 387 IsModified(&settingsChanged, &profileChanged); 388 if(!settingsChanged && !profileChanged) 389 return true; 390 391 BMessage settings, profile; 392 if(!SaveSettings(&settings, &profile, false)) 393 return false; 394 395 BDirectory settingsDirectory; 396 BDirectory profileDirectory; 397 GetPPPDirectories(&settingsDirectory, &profileDirectory); 398 if(settingsDirectory.InitCheck() != B_OK || profileDirectory.InitCheck() != B_OK) 399 return false; 400 401 BFile file; 402 if(settingsChanged) { 403 settingsDirectory.CreateFile(fCurrentItem->Label(), &file); 404 WriteMessageDriverSettings(file, settings); 405 } 406 407 if(profileChanged) { 408 profileDirectory.CreateFile(fCurrentItem->Label(), &file); 409 WriteMessageDriverSettings(file, profile); 410 } 411 412 return true; 413 } 414 415 416 void 417 DialUpView::UpDownThread() 418 { 419 SaveSettingsToFile(); 420 BMessage settings, profile; 421 SaveSettings(&settings, &profile, true); 422 // save temporary profile 423 //driver_settings *temporaryProfile = MessageToDriverSettings(profile); 424 425 PPPInterface interface; 426 if (fWatching == PPP_UNDEFINED_INTERFACE_ID) { 427 interface = fListener.Manager().InterfaceWithName(fCurrentItem->Label()); 428 if(interface.InitCheck() != B_OK) 429 interface = fListener.Manager().CreateInterfaceWithName( 430 fCurrentItem->Label()); 431 } else { 432 interface = fWatching; 433 //interface.SetProfile(temporaryProfile); 434 } 435 436 //free_driver_settings(temporaryProfile); 437 438 if(interface.InitCheck() != B_OK) { 439 Window()->Lock(); 440 fStatusView->SetText(kTextCreationError); 441 Window()->Unlock(); 442 return; 443 } 444 445 ppp_interface_info_t info; 446 interface.GetInterfaceInfo(&info); 447 if(info.info.phase == PPP_DOWN_PHASE) 448 interface.Up(); 449 else 450 interface.Down(); 451 452 fUpDownThread = -1; 453 } 454 455 456 #define PPP_INTERFACE_SETTINGS_PATH "" // FIXME! 457 void 458 DialUpView::GetPPPDirectories(BDirectory *settingsDirectory, 459 BDirectory *profileDirectory) const 460 { 461 if(settingsDirectory) { 462 BDirectory settings(PPP_INTERFACE_SETTINGS_PATH); 463 if(settings.InitCheck() != B_OK) { 464 create_directory(PPP_INTERFACE_SETTINGS_PATH, 0750); 465 settings.SetTo(PPP_INTERFACE_SETTINGS_PATH); 466 } 467 468 *settingsDirectory = settings; 469 } 470 471 if(profileDirectory) { 472 BDirectory profile(PPP_INTERFACE_SETTINGS_PATH "/profile"); 473 if(profile.InitCheck() != B_OK) { 474 create_directory(PPP_INTERFACE_SETTINGS_PATH "/profile", 0750); 475 profile.SetTo(PPP_INTERFACE_SETTINGS_PATH "/profile"); 476 } 477 478 *profileDirectory = profile; 479 } 480 } 481 482 483 void 484 DialUpView::HandleReportMessage(BMessage *message) 485 { 486 thread_id sender; 487 message->FindInt32("sender", &sender); 488 489 send_data(sender, B_OK, NULL, 0); 490 491 if(!fCurrentItem) 492 return; 493 494 ppp_interface_id id; 495 if(message->FindInt32("interface", reinterpret_cast<int32*>(&id)) != B_OK 496 || (fWatching != PPP_UNDEFINED_INTERFACE_ID && id != fWatching)) 497 return; 498 499 int32 type, code; 500 message->FindInt32("type", &type); 501 message->FindInt32("code", &code); 502 503 if(type == PPP_MANAGER_REPORT && code == PPP_REPORT_INTERFACE_CREATED) { 504 PPPInterface interface(id); 505 if(interface.InitCheck() != B_OK) 506 return; 507 508 ppp_interface_info_t info; 509 interface.GetInterfaceInfo(&info); 510 if(strcasecmp(info.info.name, fCurrentItem->Label())) 511 return; 512 513 WatchInterface(id); 514 } else if(type == PPP_CONNECTION_REPORT) { 515 if(fWatching == PPP_UNDEFINED_INTERFACE_ID) 516 return; 517 518 UpdateStatus(code); 519 } else if(type == PPP_DESTRUCTION_REPORT) { 520 if(fWatching == PPP_UNDEFINED_INTERFACE_ID) 521 return; 522 523 WatchInterface(fListener.Manager().InterfaceWithName(fCurrentItem->Label())); 524 } 525 } 526 527 528 void 529 DialUpView::CreateTabs() 530 { 531 // create tabs for all registered and valid tab add-ons 532 DialUpAddon *addon = NULL; 533 BView *target = NULL; 534 TemplateList<DialUpAddon*> addons; 535 536 for (int32 index = 0; 537 fAddons.FindPointer(DUN_TAB_ADDON_TYPE, index, 538 reinterpret_cast<void**>(&addon)) == B_OK; 539 index++) { 540 if (!addon || addon->Position() < 0) 541 continue; 542 543 int32 insertIndex = 0; 544 for(; insertIndex < addons.CountItems(); insertIndex++) { 545 if (addons.ItemAt(insertIndex)->Position() > addon->Position()) 546 break; 547 } 548 549 addons.AddItem(addon, insertIndex); 550 } 551 552 for (int32 index = 0; index < addons.CountItems(); index++) { 553 addon = addons.ItemAt(index); 554 555 target = addon->CreateView(); 556 if (target == NULL) 557 continue; 558 559 fTabView->AddTab(target, NULL); 560 } 561 } 562 563 564 void 565 DialUpView::UpdateStatus(int32 code) 566 { 567 switch(code) { 568 case PPP_REPORT_DEVICE_UP_FAILED: 569 case PPP_REPORT_AUTHENTICATION_FAILED: 570 case PPP_REPORT_DOWN_SUCCESSFUL: 571 case PPP_REPORT_CONNECTION_LOST: { 572 fConnectButton->SetLabel(kLabelConnect); 573 } break; 574 575 default: 576 fConnectButton->SetLabel(kLabelDisconnect); 577 } 578 579 // maybe the status string must not be changed (codes that set fKeepLabel to false 580 // should still be handled) 581 if(fKeepLabel && code != PPP_REPORT_GOING_UP && code != PPP_REPORT_UP_SUCCESSFUL) 582 return; 583 584 if(fListener.InitCheck() != B_OK) { 585 fStatusView->SetText(kErrorNoPPPStack); 586 return; 587 } 588 589 // only errors should set fKeepLabel to true 590 switch(code) { 591 case PPP_REPORT_GOING_UP: 592 fKeepLabel = false; 593 fStatusView->SetText(kTextConnecting); 594 break; 595 596 case PPP_REPORT_UP_SUCCESSFUL: 597 fKeepLabel = false; 598 fStatusView->SetText(kTextConnectionEstablished); 599 break; 600 601 case PPP_REPORT_DOWN_SUCCESSFUL: 602 fStatusView->SetText(kTextNotConnected); 603 break; 604 605 case PPP_REPORT_DEVICE_UP_FAILED: 606 fKeepLabel = true; 607 fStatusView->SetText(kTextDeviceUpFailed); 608 break; 609 610 case PPP_REPORT_AUTHENTICATION_REQUESTED: 611 fStatusView->SetText(kTextAuthenticating); 612 break; 613 614 case PPP_REPORT_AUTHENTICATION_FAILED: 615 fKeepLabel = true; 616 fStatusView->SetText(kTextAuthenticationFailed); 617 break; 618 619 case PPP_REPORT_CONNECTION_LOST: 620 fKeepLabel = true; 621 fStatusView->SetText(kTextConnectionLost); 622 break; 623 } 624 } 625 626 627 void 628 DialUpView::WatchInterface(ppp_interface_id ID) 629 { 630 // This method can be used to update the interface's connection status. 631 632 if(fWatching != ID) { 633 //fListener.StopWatchingInterfaces(); // FIXME 634 635 if(ID == PPP_UNDEFINED_INTERFACE_ID || fListener.WatchInterface(ID)) 636 fWatching = ID; 637 } 638 639 // update status 640 PPPInterface interface(fWatching); 641 if(interface.InitCheck() != B_OK) { 642 UpdateStatus(PPP_REPORT_DOWN_SUCCESSFUL); 643 return; 644 } 645 646 ppp_interface_info_t info; 647 interface.GetInterfaceInfo(&info); 648 649 // transform phase into status 650 switch(info.info.phase) { 651 case PPP_DOWN_PHASE: 652 UpdateStatus(PPP_REPORT_DOWN_SUCCESSFUL); 653 break; 654 655 case PPP_TERMINATION_PHASE: 656 break; 657 658 case PPP_ESTABLISHED_PHASE: 659 UpdateStatus(PPP_REPORT_UP_SUCCESSFUL); 660 break; 661 662 default: 663 UpdateStatus(PPP_REPORT_GOING_UP); 664 } 665 } 666 667 668 void 669 DialUpView::LoadInterfaces() 670 { 671 fInterfaceMenu->AddSeparatorItem(); 672 fInterfaceMenu->AddItem(new BMenuItem(kLabelCreateNewInterface, 673 new BMessage(kMsgCreateNew))); 674 fDeleterItem = new BMenuItem(kLabelDeleteCurrent, 675 new BMessage(kMsgDeleteCurrent)); 676 fInterfaceMenu->AddItem(fDeleterItem); 677 678 BDirectory settingsDirectory; 679 BEntry entry; 680 BPath path; 681 GetPPPDirectories(&settingsDirectory, NULL); 682 while(settingsDirectory.GetNextEntry(&entry) == B_OK) { 683 if(entry.IsFile()) { 684 entry.GetPath(&path); 685 AddInterface(path.Leaf(), true); 686 } 687 } 688 } 689 690 691 void 692 DialUpView::LoadAddons() 693 { 694 // Load integrated add-ons: 695 // "Connection Options" tab 696 ConnectionOptionsAddon *connectionOptionsAddon = 697 new ConnectionOptionsAddon(&fAddons); 698 fAddons.AddPointer(DUN_TAB_ADDON_TYPE, connectionOptionsAddon); 699 fAddons.AddPointer(DUN_DELETE_ON_QUIT, connectionOptionsAddon); 700 // "General" tab 701 GeneralAddon *fGeneralAddon = new GeneralAddon(&fAddons); 702 fAddons.AddPointer(DUN_TAB_ADDON_TYPE, fGeneralAddon); 703 fAddons.AddPointer(DUN_DELETE_ON_QUIT, fGeneralAddon); 704 705 // "IPCP" protocol 706 IPCPAddon *ipcpAddon = new IPCPAddon(&fAddons); 707 fAddons.AddPointer(DUN_TAB_ADDON_TYPE, ipcpAddon); 708 fAddons.AddPointer(DUN_DELETE_ON_QUIT, ipcpAddon); 709 // "PPPoE" device 710 PPPoEAddon *pppoeAddon = new PPPoEAddon(&fAddons); 711 fAddons.AddPointer(DUN_DEVICE_ADDON_TYPE, pppoeAddon); 712 fAddons.AddPointer(DUN_DELETE_ON_QUIT, pppoeAddon); 713 714 // "PAP" authenticator 715 BMessage addon; 716 addon.AddString("FriendlyName", "Plain-text Authentication"); 717 addon.AddString("TechnicalName", "PAP"); 718 addon.AddString("KernelModuleName", "pap"); 719 fAddons.AddMessage(DUN_AUTHENTICATOR_ADDON_TYPE, &addon); 720 // addon.MakeEmpty(); // for next authenticator 721 722 // TODO: 723 // load all add-ons from the add-ons folder 724 } 725 726 727 void 728 DialUpView::AddInterface(const char *name, bool isNew) 729 { 730 if(fInterfaceMenu->FindItem(name)) { 731 (new BAlert(kErrorTitle, kErrorInterfaceExists, kLabelOK, 732 NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL); 733 return; 734 } 735 736 BMenuItem *item = new BMenuItem(name, new BMessage(kMsgSelectInterface)); 737 item->SetTarget(this); 738 int32 index = FindNextMenuInsertionIndex(fInterfaceMenu, name); 739 if(index > CountInterfaces()) 740 index = CountInterfaces(); 741 fInterfaceMenu->AddItem(item, index); 742 UpdateControls(); 743 744 item->SetMarked(true); 745 SelectInterface(index, isNew); 746 } 747 748 749 void 750 DialUpView::SelectInterface(int32 index, bool isNew) 751 { 752 BMenuItem *item = fInterfaceMenu->FindMarked(); 753 if(fCurrentItem && item == fCurrentItem) 754 return; 755 756 if(fCurrentItem && !SaveSettingsToFile()) 757 (new BAlert(kErrorTitle, kErrorSavingFailed, kLabelOK, 758 NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL); 759 760 if(index >= CountInterfaces() || index < 0) { 761 if(CountInterfaces() > 0) 762 SelectInterface(0); 763 else { 764 fCurrentItem = NULL; 765 WatchInterface(PPP_UNDEFINED_INTERFACE_ID); 766 } 767 } else { 768 fCurrentItem = fInterfaceMenu->ItemAt(index); 769 if(!fCurrentItem) { 770 SelectInterface(0); 771 return; 772 } 773 774 fCurrentItem->SetMarked(true); 775 fDeleterItem->SetEnabled(true); 776 WatchInterface(fListener.Manager().InterfaceWithName(fCurrentItem->Label())); 777 } 778 779 if(!fCurrentItem) 780 LoadSettings(false); 781 // tell modules to unload all settings 782 else if(!isNew && !LoadSettings(false)) { 783 (new BAlert(kErrorTitle, kErrorLoadingFailed, kLabelOK, 784 NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL); 785 LoadSettings(true); 786 } else if(isNew && !LoadSettings(true)) 787 (new BAlert(kErrorTitle, kErrorLoadingFailed, kLabelOK, 788 NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go(NULL); 789 } 790 791 792 int32 793 DialUpView::CountInterfaces() const 794 { 795 return fInterfaceMenu->CountItems() - 3; 796 } 797 798 799 void 800 DialUpView::UpdateControls() 801 { 802 if(fTabView->IsHidden() && CountInterfaces() > 0) { 803 fInterfaceMenu->SetLabelFromMarked(true); 804 fStringView->Hide(); 805 fCreateNewButton->Hide(); 806 fTabView->Show(); 807 fConnectButton->SetEnabled(true); 808 } else if(!fTabView->IsHidden() && CountInterfaces() == 0) { 809 fDeleterItem->SetEnabled(false); 810 fInterfaceMenu->SetRadioMode(false); 811 fInterfaceMenu->Superitem()->SetLabel(kLabelCreateNew); 812 fTabView->Hide(); 813 fStringView->Show(); 814 fCreateNewButton->Show(); 815 fConnectButton->SetEnabled(false); 816 } 817 } 818