diff --git a/src/apps/bemail/Header.cpp b/src/apps/bemail/Header.cpp index 002bff9dde..38e4d5439e 100644 --- a/src/apps/bemail/Header.cpp +++ b/src/apps/bemail/Header.cpp @@ -49,6 +49,7 @@ All rights reserved. #include #include #include +#include #include #include #include @@ -76,6 +77,7 @@ extern uint32 gDefaultChain; const char *kDateLabel = "Date:"; const uint32 kMsgFrom = 'hFrm'; const uint32 kMsgEncoding = 'encd'; +const uint32 kMsgAddressChosen = 'acsn'; class QPopupMenu : public QueryMenu { @@ -718,7 +720,8 @@ THeaderView::LoadMessage(BEmailMessage *mail) TTextControl::TTextControl(BRect rect, char *label, BMessage *msg, bool incoming, bool resending, int32 resizingMode) - : BComboBox(rect, "happy", label, msg, resizingMode) + : BComboBox(rect, "happy", label, msg, resizingMode), + fRefDropMenu(NULL) //:BTextControl(rect, "happy", label, "", msg, resizingMode) { strcpy(fLabel, label); @@ -750,75 +753,123 @@ void TTextControl::MessageReceived(BMessage *msg) { switch (msg->what) { - case B_SIMPLE_DATA: - if (!fIncoming || fResending) { - BMessage message(REFS_RECEIVED); - bool enclosure = false; - BString addressList; - // Batch up the addresses to be added, since we can only - // insert a few times before deadlocking since inserting - // sends a notification message to the window BLooper, - // which is busy doing this insert. BeOS message queues - // are annoyingly limited in their design. + case B_SIMPLE_DATA: { + if ((fIncoming == true) && (fResending == false)) return; + + int32 buttons = -1; + BPoint point; - entry_ref ref; - for (int32 index = 0;msg->FindRef("refs", index, &ref) == B_OK; index++) { - BFile file(&ref, B_READ_ONLY); - if (file.InitCheck() == B_NO_ERROR) { - BNodeInfo node(&file); - char type[B_FILE_NAME_LENGTH]; - node.GetType(type); + if (msg->FindInt32("buttons", &buttons) != B_OK) { + buttons = B_PRIMARY_MOUSE_BUTTON; + }; + if (buttons != B_PRIMARY_MOUSE_BUTTON) { + if (msg->FindPoint("_drop_point_", &point) != B_OK) return; + }; + + BMessage message(REFS_RECEIVED); + bool enclosure = false; + BString addressList; + // Batch up the addresses to be added, since we can only + // insert a few times before deadlocking since inserting + // sends a notification message to the window BLooper, + // which is busy doing this insert. BeOS message queues + // are annoyingly limited in their design. - if (fCommand != SUBJECT_FIELD && - !strcmp(type,"application/x-person")) { - // add person's E-mail address to the To: field + entry_ref ref; + for (int32 index = 0;msg->FindRef("refs", index, &ref) == B_OK; index++) { + BFile file(&ref, B_READ_ONLY); + if (file.InitCheck() == B_NO_ERROR) { + BNodeInfo info(&file); + char type[B_FILE_NAME_LENGTH]; + info.GetType(type); - const char *attr; + if (fCommand != SUBJECT_FIELD && + !strcmp(type,"application/x-person")) { + // add person's E-mail address to the To: field + + BString attr = ""; + if (buttons == B_PRIMARY_MOUSE_BUTTON) { + if (msg->FindString("attr", &attr) < B_OK) attr = "META:email"; // If not META:email3 etc. - - BString email; - ReadAttrString(&file,attr,&email); - - /* we got something... */ - if (email.Length() > 0) { - /* see if we can get a username as well */ - BString name; - ReadAttrString(&file,"META:name",&name); - - BString address; - /* if we have no Name, just use the email address */ - if (name.Length() == 0) - address = email; - else { - /* otherwise, pretty-format it */ - address << "\"" << name << "\" <" << email << ">"; - } - if (addressList.Length() > 0) - addressList << ", "; - addressList << address; - } } else { - enclosure = true; - message.AddRef("refs", &ref); + BNode node(&ref); + node.RewindAttrs(); + + char buffer[B_ATTR_NAME_LENGTH]; + + if (fRefDropMenu) delete fRefDropMenu; + fRefDropMenu = new BPopUpMenu("RecipientMenu"); + + while (node.GetNextAttrName(buffer) == B_OK) { + if (strstr(buffer, "email") <= 0) continue; + attr = buffer; + + BString address; + ReadAttrString(&node, buffer, &address); + if (address.Length() <= 0) continue; + + BMessage *itemMsg = new BMessage(kMsgAddressChosen); + itemMsg->AddString("address", address.String()); + itemMsg->AddRef("ref", &ref); + + BMenuItem *item = new BMenuItem(address.String(), + itemMsg); + fRefDropMenu->AddItem(item); + }; + + if (fRefDropMenu->CountItems() > 1) { + fRefDropMenu->SetTargetForItems(this); + fRefDropMenu->Go(point, true, true, true); + return; + } else { + delete fRefDropMenu; + fRefDropMenu = NULL; + }; + }; + + BString email; + ReadAttrString(&file,attr.String(),&email); + + /* we got something... */ + if (email.Length() > 0) { + /* see if we can get a username as well */ + BString name; + ReadAttrString(&file,"META:name",&name); + + BString address; + /* if we have no Name, just use the email address */ + if (name.Length() == 0) + address = email; + else { + /* otherwise, pretty-format it */ + address << "\"" << name << "\" <" << email << ">"; + } + if (addressList.Length() > 0) + addressList << ", "; + addressList << address; } + } else { + enclosure = true; + message.AddRef("refs", &ref); } } - - if (addressList.Length() > 0) { - BTextView *textView = TextView(); - int end = textView->TextLength(); - if (end != 0) { - textView->Select(end, end); - textView->Insert(", "); - } - textView->Insert(addressList.String()); - } - - if (enclosure) - Window()->PostMessage(&message, Window()); } + + if (addressList.Length() > 0) { + BTextView *textView = TextView(); + int end = textView->TextLength(); + if (end != 0) { + textView->Select(end, end); + textView->Insert(", "); + } + textView->Insert(addressList.String()); + } + + if (enclosure) Window()->PostMessage(&message, Window()); + break; + }; case M_SELECT: { @@ -828,6 +879,37 @@ TTextControl::MessageReceived(BMessage *msg) break; } + case kMsgAddressChosen: { + BString display; + BString address; + entry_ref ref; + + if (msg->FindString("address", &address) != B_OK) return; + if (msg->FindRef("ref", &ref) != B_OK) return; + + if (address.Length() > 0) { + BString name; + BNode node(&ref); + + display = address; + + ReadAttrString(&node, "META:name", &name); + if (name.Length() > 0) { + display = ""; + display << "\"" << name << "\" <" << address << ">"; + }; + + BTextView *textView = TextView(); + int end = textView->TextLength(); + if (end != 0) { + textView->Select(end, end); + textView->Insert(", "); + }; + textView->Insert(display.String()); + + }; + } break; + default: // BTextControl::MessageReceived(msg); BComboBox::MessageReceived(msg); diff --git a/src/apps/bemail/Header.h b/src/apps/bemail/Header.h index 2a0035c1c2..3c2a5fbfd6 100644 --- a/src/apps/bemail/Header.h +++ b/src/apps/bemail/Header.h @@ -143,6 +143,7 @@ class TTextControl : public BComboBox bool fIncoming; bool fResending; char fLabel[100]; + BPopUpMenu *fRefDropMenu; int32 fCommand; }; diff --git a/src/apps/bemail/QueryMenu.cpp b/src/apps/bemail/QueryMenu.cpp index 7101af059c..2a241e4ca9 100644 --- a/src/apps/bemail/QueryMenu.cpp +++ b/src/apps/bemail/QueryMenu.cpp @@ -106,9 +106,9 @@ QueryMenu::QueryMenu(const char *title, bool popUp, bool radioMode, bool autoRen fQueryLooper->AddHandler(fQueryHandler); fQueryLooper->Unlock(); - BMessenger mercury(fQueryHandler, fQueryLooper); - fQuery = new BQuery(); - fQuery->SetTarget(mercury); +// BMessenger mercury(fQueryHandler, fQueryLooper); +// fQuery = new BQuery(); +// fQuery->SetTarget(mercury); } @@ -116,7 +116,12 @@ QueryMenu::~QueryMenu(void) { fCancelQuery = true; fQueryLock.Lock(); - delete fQuery; + + int32 queries = fQueries.size(); + for (int i = 0; i < queries; i++) { + fQueries[i]->Clear(); + delete fQueries[i]; + }; fQueryLock.Unlock(); fQueryLooper->Lock(); @@ -160,22 +165,52 @@ void QueryMenu::DoQueryMessage(BMessage *msg) status_t QueryMenu::SetPredicate(const char *expr, BVolume *volume) { - status_t status; +// status_t status; + + if (volume == NULL) { + BVolumeRoster roster; + BVolume volume; + BMessenger mercury(fQueryHandler, fQueryLooper); + + roster.Rewind(); + while (roster.GetNextVolume(&volume) == B_NO_ERROR) { + if ((volume.KnowsQuery() == true) && (volume.KnowsAttr() == true) && + (volume.KnowsMime() == true)) { + + BQuery *query = new BQuery(); + if (query->SetVolume(&volume) != B_OK) { + delete query; + continue; + }; + if (query->SetPredicate(expr) != B_OK) { + delete query; + continue; + }; + if (query->SetTarget(mercury) != B_OK) { + delete query; + continue; + }; + + fQueries.push_back(query); + }; + }; + } else { + }; // Set the volume - if (volume == NULL) - { - BVolume bootVolume; - BVolumeRoster().GetBootVolume(&bootVolume); - - if ( (status = fQuery->SetVolume(&bootVolume)) != B_OK) - return status; - } - else if ((status = fQuery->SetVolume(volume)) != B_OK) - return status; - - if ((status = fQuery->SetPredicate(expr)) < B_OK) - return status; +// if (volume == NULL) +// { +// BVolume bootVolume; +// BVolumeRoster().GetBootVolume(&bootVolume); +// +// if ( (status = fQuery->SetVolume(&bootVolume)) != B_OK) +// return status; +// } +// else if ((status = fQuery->SetVolume(volume)) != B_OK) +// return status; +// +// if ((status = fQuery->SetPredicate(expr)) < B_OK) +// return status; // Force query thread to exit if still running fCancelQuery = true; @@ -219,17 +254,22 @@ int32 QueryMenu::QueryThread() // Begin resolving query fCancelQuery = false; - fQuery->Fetch(); - - // Build Menu - entry_ref ref; - node_ref node; - while (fQuery->GetNextRef(&ref) == B_OK && !fCancelQuery) - { - BEntry entry(&ref); - entry.GetNodeRef(&node); - EntryCreated(ref, node.node); - } + int32 queries = fQueries.size(); + for (int i = 0; i < queries; i++) { + BQuery *query = fQueries[i]; + + query->Fetch(); + + // Build Menu + entry_ref ref; + node_ref node; + while (query->GetNextRef(&ref) == B_OK && !fCancelQuery) + { + BEntry entry(&ref); + entry.GetNodeRef(&node); + EntryCreated(ref, node.node); + } + }; // Remove the group separator if there are no groups or no items without groups BMenuItem *item; @@ -272,8 +312,9 @@ void QueryMenu::EntryCreated(const entry_ref &ref, ino_t node) msg->AddRef("refs", &ref); msg->AddInt64("node", node); item = new BMenuItem(ref.name, msg); - if (fTargetHandler) + if (fTargetHandler) { item->SetTarget(fTargetHandler); + }; AddItem(item); } diff --git a/src/apps/bemail/QueryMenu.h b/src/apps/bemail/QueryMenu.h index 039b6bab97..dca838036f 100644 --- a/src/apps/bemail/QueryMenu.h +++ b/src/apps/bemail/QueryMenu.h @@ -38,11 +38,15 @@ All rights reserved. #include #include +#include + class BLooper; class BQuery; class BVolume; class QHandler; +typedef vector query_t; + class QueryMenu : public BPopUpMenu { friend QHandler; @@ -70,7 +74,8 @@ class QueryMenu : public BPopUpMenu { int32 QueryThread(void); BLocker fQueryLock; - BQuery *fQuery; +// BQuery *fQuery; + query_t fQueries; QHandler *fQueryHandler; bool fCancelQuery; bool fPopUp;