1 /* 2 * Copyright 20011, Haiku Inc. All Rights Reserved. 3 * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 //! The standard config view for all protocols. 9 10 11 #include "ProtocolConfigView.h" 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 16 #include <Catalog.h> 17 #include <CheckBox.h> 18 #include <MenuField.h> 19 #include <MenuItem.h> 20 #include <Message.h> 21 #include <PopUpMenu.h> 22 #include <String.h> 23 #include <TextControl.h> 24 25 #include <crypt.h> 26 27 28 #undef B_TRANSLATION_CONTEXT 29 #define B_TRANSLATION_CONTEXT "ProtocolConfigView" 30 31 32 const char* kPartialDownloadLimit = "partial_download_limit"; 33 34 35 BodyDownloadConfig::BodyDownloadConfig() 36 : 37 BView(BRect(0,0,50,50), "body_config", B_FOLLOW_ALL_SIDES, 0) 38 { 39 const char *partial_text = B_TRANSLATE( 40 "Partially download messages larger than"); 41 42 BRect r(0, 0, 280, 15); 43 fPartialBox = new BCheckBox(r, "size_if", partial_text, 44 new BMessage('SIZF')); 45 fPartialBox->ResizeToPreferred(); 46 47 r = fPartialBox->Frame(); 48 r.OffsetBy(17,r.Height() + 1); 49 r.right = r.left + be_plain_font->StringWidth("0000") + 10; 50 fSizeBox = new BTextControl(r, "size", "", "", NULL); 51 52 r.OffsetBy(r.Width() + 5,0); 53 fBytesLabel = new BStringView(r, "kb", B_TRANSLATE("KiB")); 54 AddChild(fBytesLabel); 55 fSizeBox->SetDivider(0); 56 57 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 58 AddChild(fPartialBox); 59 AddChild(fSizeBox); 60 ResizeToPreferred(); 61 } 62 63 64 void 65 BodyDownloadConfig::SetTo(MailAddonSettings& addonSettings) 66 { 67 const BMessage* settings = &addonSettings.Settings(); 68 69 int32 limit = 0; 70 if (settings->HasInt32(kPartialDownloadLimit)) 71 limit = settings->FindInt32(kPartialDownloadLimit); 72 if (limit < 0) { 73 fPartialBox->SetValue(B_CONTROL_OFF); 74 fSizeBox->SetText("0"); 75 fSizeBox->SetEnabled(false); 76 } else { 77 limit = int32(limit / 1024); 78 BString kb; 79 kb << limit; 80 fSizeBox->SetText(kb); 81 fPartialBox->SetValue(B_CONTROL_ON); 82 fSizeBox->SetEnabled(true); 83 } 84 } 85 86 87 void 88 BodyDownloadConfig::MessageReceived(BMessage *msg) 89 { 90 if (msg->what != 'SIZF') 91 return BView::MessageReceived(msg); 92 fSizeBox->SetEnabled(fPartialBox->Value()); 93 } 94 95 96 void 97 BodyDownloadConfig::AttachedToWindow() 98 { 99 fPartialBox->SetTarget(this); 100 fPartialBox->ResizeToPreferred(); 101 } 102 103 104 void 105 BodyDownloadConfig::GetPreferredSize(float *width, float *height) 106 { 107 *height = fSizeBox->Frame().bottom + 5; 108 *width = 200; 109 } 110 111 112 status_t 113 BodyDownloadConfig::Archive(BMessage* into, bool) const 114 { 115 into->RemoveName(kPartialDownloadLimit); 116 if (fPartialBox->Value() == B_CONTROL_ON) 117 into->AddInt32(kPartialDownloadLimit, atoi(fSizeBox->Text()) * 1024); 118 else 119 into->AddInt32(kPartialDownloadLimit, -1); 120 121 return B_OK; 122 } 123 124 125 namespace { 126 127 //--------------------Support functions and #defines--------------- 128 #define enable_control(name) if (FindView(name) != NULL) ((BControl *)(FindView(name)))->SetEnabled(true) 129 #define disable_control(name) if (FindView(name) != NULL) ((BControl *)(FindView(name)))->SetEnabled(false) 130 131 BTextControl *AddTextField (BRect &rect, const char *name, const char *label); 132 BMenuField *AddMenuField (BRect &rect, const char *name, const char *label); 133 float FindWidestLabel(BView *view); 134 135 static float sItemHeight; 136 137 inline const char * 138 TextControl(BView *parent,const char *name) 139 { 140 BTextControl *control = (BTextControl *)(parent->FindView(name)); 141 if (control != NULL) 142 return control->Text(); 143 144 return ""; 145 } 146 147 148 BTextControl * 149 AddTextField(BRect &rect, const char *name, const char *label) 150 { 151 BTextControl *text_control = new BTextControl(rect,name,label,"",NULL,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 152 // text_control->SetDivider(be_plain_font->StringWidth(label)); 153 rect.OffsetBy(0,sItemHeight); 154 return text_control; 155 } 156 157 158 BMenuField *AddMenuField (BRect &rect, const char *name, const char *label) { 159 BPopUpMenu *menu = new BPopUpMenu("Select"); 160 BMenuField *control = new BMenuField(rect,name,label,menu,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 161 control->SetDivider(be_plain_font->StringWidth(label) + 6); 162 rect.OffsetBy(0,sItemHeight); 163 return control; 164 } 165 166 167 inline BCheckBox * 168 AddCheckBox(BRect &rect, const char *name, const char *label, BMessage *msg = NULL) 169 { 170 BCheckBox *control = new BCheckBox(rect,name,label,msg); 171 rect.OffsetBy(0,sItemHeight); 172 return control; 173 } 174 175 176 inline void 177 SetTextControl(BView *parent, const char *name, const char *text) 178 { 179 BTextControl *control = (BTextControl *)(parent->FindView(name)); 180 if (control != NULL) 181 control->SetText(text); 182 } 183 184 185 float 186 FindWidestLabel(BView *view) 187 { 188 float width = 0; 189 for (int32 i = view->CountChildren();i-- > 0;) { 190 if (BControl *control = dynamic_cast<BControl *>(view->ChildAt(i))) { 191 float labelWidth = control->StringWidth(control->Label()); 192 if (labelWidth > width) 193 width = labelWidth; 194 } 195 } 196 return width; 197 } 198 199 } // unnamed namspace 200 201 202 //----------------Real code---------------------- 203 BMailProtocolConfigView::BMailProtocolConfigView(uint32 options_mask) 204 : 205 BView (BRect(0,0,100,20), "protocol_config_view", B_FOLLOW_LEFT 206 | B_FOLLOW_TOP, B_WILL_DRAW), 207 fBodyDownloadConfig(NULL) 208 { 209 BRect rect(5,5,245,25); 210 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 211 212 // determine font height 213 font_height fontHeight; 214 GetFontHeight(&fontHeight); 215 sItemHeight = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 13; 216 rect.bottom = rect.top - 2 + sItemHeight; 217 218 if (options_mask & B_MAIL_PROTOCOL_HAS_HOSTNAME) 219 AddChild(AddTextField(rect, "host", B_TRANSLATE("Mail server:"))); 220 221 if (options_mask & B_MAIL_PROTOCOL_HAS_USERNAME) 222 AddChild(AddTextField(rect, "user", B_TRANSLATE("Username:"))); 223 224 if (options_mask & B_MAIL_PROTOCOL_HAS_PASSWORD) { 225 BTextControl *control = AddTextField(rect, "pass", 226 B_TRANSLATE("Password:")); 227 control->TextView()->HideTyping(true); 228 AddChild(control); 229 } 230 231 if (options_mask & B_MAIL_PROTOCOL_HAS_FLAVORS) 232 AddChild(AddMenuField(rect, "flavor", B_TRANSLATE("Connection type:"))); 233 234 if (options_mask & B_MAIL_PROTOCOL_HAS_AUTH_METHODS) 235 AddChild(AddMenuField(rect, "auth_method", B_TRANSLATE("Login type:"))); 236 237 // set divider 238 float width = FindWidestLabel(this); 239 for (int32 i = CountChildren();i-- > 0;) { 240 if (BTextControl *text = dynamic_cast<BTextControl *>(ChildAt(i))) 241 text->SetDivider(width + 6); 242 } 243 244 if (options_mask & B_MAIL_PROTOCOL_CAN_LEAVE_MAIL_ON_SERVER) { 245 AddChild(AddCheckBox(rect, "leave_mail_on_server", 246 B_TRANSLATE("Leave mail on server"), new BMessage('lmos'))); 247 BCheckBox* box = AddCheckBox(rect, "delete_remote_when_local", 248 B_TRANSLATE("Remove mail from server when deleted")); 249 box->SetEnabled(false); 250 AddChild(box); 251 } 252 253 if (options_mask & B_MAIL_PROTOCOL_PARTIAL_DOWNLOAD) { 254 fBodyDownloadConfig = new BodyDownloadConfig(); 255 fBodyDownloadConfig->MoveBy(0, rect.bottom + 5); 256 AddChild(fBodyDownloadConfig); 257 } 258 259 // resize views 260 float height; 261 GetPreferredSize(&width,&height); 262 ResizeTo(width,height); 263 for (int32 i = CountChildren();i-- > 0;) { 264 // this doesn't work with BTextControl, does anyone know why? -- axeld. 265 if (BView *view = ChildAt(i)) 266 view->ResizeTo(width - 10,view->Bounds().Height()); 267 } 268 } 269 270 271 BMailProtocolConfigView::~BMailProtocolConfigView() 272 { 273 } 274 275 276 void 277 BMailProtocolConfigView::SetTo(MailAddonSettings& settings) 278 { 279 const BMessage* archive = &settings.Settings(); 280 281 BString host = archive->FindString("server"); 282 if (archive->HasInt32("port")) 283 host << ':' << archive->FindInt32("port"); 284 285 SetTextControl(this,"host", host.String()); 286 SetTextControl(this,"user", archive->FindString("username")); 287 288 char *password = get_passwd(archive, "cpasswd"); 289 if (password) { 290 SetTextControl(this,"pass", password); 291 delete[] password; 292 } else 293 SetTextControl(this,"pass", archive->FindString("password")); 294 295 if (archive->HasInt32("flavor")) { 296 BMenuField *menu = (BMenuField *)(FindView("flavor")); 297 if (menu != NULL) { 298 if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("flavor"))) 299 item->SetMarked(true); 300 } 301 } 302 303 if (archive->HasInt32("auth_method")) { 304 BMenuField *menu = (BMenuField *)(FindView("auth_method")); 305 if (menu != NULL) { 306 if (BMenuItem *item = menu->Menu()->ItemAt(archive->FindInt32("auth_method"))) { 307 item->SetMarked(true); 308 if (item->Command() != 'none') { 309 enable_control("user"); 310 enable_control("pass"); 311 } 312 } 313 } 314 } 315 316 317 BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server")); 318 if (box != NULL) 319 box->SetValue(archive->FindBool("leave_mail_on_server") ? B_CONTROL_ON : B_CONTROL_OFF); 320 321 box = (BCheckBox *)(FindView("delete_remote_when_local")); 322 if (box != NULL) { 323 box->SetValue(archive->FindBool("delete_remote_when_local") ? B_CONTROL_ON : B_CONTROL_OFF); 324 325 if (archive->FindBool("leave_mail_on_server")) 326 box->SetEnabled(true); 327 else 328 box->SetEnabled(false); 329 } 330 331 if (fBodyDownloadConfig) 332 fBodyDownloadConfig->SetTo(settings); 333 } 334 335 336 void 337 BMailProtocolConfigView::AddFlavor(const char *label) 338 { 339 BMenuField *menu = (BMenuField *)(FindView("flavor")); 340 if (menu != NULL) { 341 menu->Menu()->AddItem(new BMenuItem(label,NULL)); 342 if (menu->Menu()->FindMarked() == NULL) 343 menu->Menu()->ItemAt(0)->SetMarked(true); 344 } 345 } 346 347 348 void 349 BMailProtocolConfigView::AddAuthMethod(const char *label,bool needUserPassword) 350 { 351 BMenuField *menu = (BMenuField *)(FindView("auth_method")); 352 if (menu != NULL) { 353 BMenuItem *item = new BMenuItem(label,new BMessage(needUserPassword ? 'some' : 'none')); 354 355 menu->Menu()->AddItem(item); 356 357 if (menu->Menu()->FindMarked() == NULL) { 358 menu->Menu()->ItemAt(0)->SetMarked(true); 359 MessageReceived(menu->Menu()->ItemAt(0)->Message()); 360 } 361 } 362 } 363 364 365 void 366 BMailProtocolConfigView::AttachedToWindow() 367 { 368 BMenuField *menu = (BMenuField *)(FindView("auth_method")); 369 if (menu != NULL) 370 menu->Menu()->SetTargetForItems(this); 371 372 BCheckBox *box = (BCheckBox *)(FindView("leave_mail_on_server")); 373 if (box != NULL) 374 box->SetTarget(this); 375 } 376 377 378 void 379 BMailProtocolConfigView::MessageReceived(BMessage *msg) 380 { 381 switch (msg->what) { 382 case 'some': 383 enable_control("user"); 384 enable_control("pass"); 385 break; 386 case 'none': 387 disable_control("user"); 388 disable_control("pass"); 389 break; 390 391 case 'lmos': 392 if (msg->FindInt32("be:value") == 1) { 393 enable_control("delete_remote_when_local"); 394 } else { 395 disable_control("delete_remote_when_local"); 396 } 397 break; 398 } 399 } 400 401 402 status_t 403 BMailProtocolConfigView::Archive(BMessage *into, bool deep) const 404 { 405 const char *host = TextControl((BView *)this,"host"); 406 int32 port = -1; 407 BString host_name = host; 408 if (host_name.FindFirst(':') > -1) { 409 port = atol(host_name.String() + host_name.FindFirst(':') + 1); 410 host_name.Truncate(host_name.FindFirst(':')); 411 } 412 413 if (into->ReplaceString("server",host_name.String()) != B_OK) 414 into->AddString("server",host_name.String()); 415 416 // since there is no need for the port option, remove it here 417 into->RemoveName("port"); 418 if (port != -1) 419 into->AddInt32("port",port); 420 421 if (into->ReplaceString("username",TextControl((BView *)this,"user")) != B_OK) 422 into->AddString("username",TextControl((BView *)this,"user")); 423 424 // remove old unencrypted passwords 425 into->RemoveName("password"); 426 427 set_passwd(into,"cpasswd",TextControl((BView *)this,"pass")); 428 429 BMenuField *field; 430 int32 index = -1; 431 432 if ((field = (BMenuField *)(FindView("flavor"))) != NULL) { 433 BMenuItem *item = field->Menu()->FindMarked(); 434 if (item != NULL) 435 index = field->Menu()->IndexOf(item); 436 } 437 438 if (into->ReplaceInt32("flavor",index) != B_OK) 439 into->AddInt32("flavor",index); 440 441 index = -1; 442 443 if ((field = (BMenuField *)(FindView("auth_method"))) != NULL) { 444 BMenuItem *item = field->Menu()->FindMarked(); 445 if (item != NULL) 446 index = field->Menu()->IndexOf(item); 447 } 448 449 if (into->ReplaceInt32("auth_method",index) != B_OK) 450 into->AddInt32("auth_method",index); 451 452 if (FindView("leave_mail_on_server") != NULL) { 453 BControl* control = (BControl*)FindView("leave_mail_on_server"); 454 bool on = (control->Value() == B_CONTROL_ON); 455 if (into->ReplaceBool("leave_mail_on_server", on) != B_OK) 456 into->AddBool("leave_mail_on_server", on); 457 458 control = (BControl*)FindView("delete_remote_when_local"); 459 on = (control->Value() == B_CONTROL_ON); 460 if (into->ReplaceBool("delete_remote_when_local", on)) { 461 into->AddBool("delete_remote_when_local", on); 462 } 463 } else { 464 if (into->ReplaceBool("leave_mail_on_server", false) != B_OK) 465 into->AddBool("leave_mail_on_server", false); 466 467 if (into->ReplaceBool("delete_remote_when_local", false) != B_OK) 468 into->AddBool("delete_remote_when_local", false); 469 } 470 471 if (fBodyDownloadConfig) 472 fBodyDownloadConfig->Archive(into, deep); 473 return B_OK; 474 } 475 476 477 void 478 BMailProtocolConfigView::GetPreferredSize(float *width, float *height) 479 { 480 float minWidth = 250; 481 if (BView *view = FindView("delete_remote_when_local")) { 482 float ignore; 483 view->GetPreferredSize(&minWidth,&ignore); 484 } 485 if (minWidth < 250) 486 minWidth = 250; 487 *width = minWidth + 10; 488 *height = (CountChildren() * sItemHeight) + 5; 489 490 if (fBodyDownloadConfig) { 491 float bodyW, bodyH; 492 fBodyDownloadConfig->GetPreferredSize(&bodyW, &bodyH); 493 *height+= bodyH; 494 } 495 } 496 497