diff --git a/src/apps/mail/Jamfile b/src/apps/mail/Jamfile index b7a45c5ac9..a4ca96ea53 100644 --- a/src/apps/mail/Jamfile +++ b/src/apps/mail/Jamfile @@ -10,6 +10,7 @@ if $(TARGET_PLATFORM) != haiku { UsePrivateHeaders mail ; UsePrivateHeaders textencoding ; UsePrivateHeaders shared ; +UsePrivateHeaders storage ; AddResources Mail : Mail.rdef pictures.rdef ; Application Mail : diff --git a/src/apps/mail/MailWindow.cpp b/src/apps/mail/MailWindow.cpp index 8f4d466b47..81a81ec2e1 100644 --- a/src/apps/mail/MailWindow.cpp +++ b/src/apps/mail/MailWindow.cpp @@ -48,6 +48,9 @@ All rights reserved. #include #include #include +#ifdef __HAIKU__ +# include +#endif #include #include #include @@ -118,6 +121,16 @@ static const char *kSpamMenuItemTextArray[] = { "Mark as Genuine" // M_TRAIN_GENUINE }; +static const char *kQueriesDirectory = "mail/queries"; +static const char *kAttrQueryInitialMode = "_trk/qryinitmode"; // taken from src/kits/tracker/Attributes.h +static const char *kAttrQueryInitialString = "_trk/qryinitstr"; +static const char *kAttrQueryInitialNumAttrs = "_trk/qryinitnumattrs"; +static const char *kAttrQueryInitialAttrs = "_trk/qryinitattrs"; +static const uint32 kAttributeItemMain = 'Fatr'; // taken from src/kits/tracker/FindPanel.h +static const uint32 kByNameItem = 'Fbyn'; // taken from src/kits/tracker/FindPanel.h +static const uint32 kByAttributeItem = 'Fbya'; // taken from src/kits/tracker/FindPanel.h +static const uint32 kByForumlaItem = 'Fbyq'; // taken from src/kits/tracker/FindPanel.h + // static list for tracking of Windows BList TMailWindow::sWindowList; @@ -270,9 +283,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, INDEX_STATUS, M_STATUS, false, false), new BMessage(M_CLOSE_CUSTOM))); #endif menu->AddItem(subMenu); - } - else - { + } else { menu->AddSeparatorItem(); menu->AddItem(new BMenuItem( MDR_DIALECT_CHOICE ("Close", "W) 閉じる"), @@ -343,9 +354,11 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, new BMessage(M_PREFS),',')); item->SetTarget(be_app); menu_bar->AddItem(menu); - + + // // View Menu - + // + if (!resending && fIncoming) { menu = new BMenu("View"); menu->AddItem(fHeader = new BMenuItem(MDR_DIALECT_CHOICE ("Show Header","H) ヘッダーを表示"), new BMessage(M_HEADER), 'H')); @@ -461,6 +474,17 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, menu_bar->AddItem(menu); } + // + // Queries Menu + // + fQueryMenu = new BMenu(MDR_DIALECT_CHOICE("Queries","???")); + menu_bar->AddItem(fQueryMenu); + + _RebuildQueryMenu(true); + + // + // Menu Bar + // AddChild(menu_bar); height = menu_bar->Bounds().bottom + 1; @@ -1486,6 +1510,51 @@ TMailWindow::MessageReceived(BMessage *msg) fContentView->fTextView->EnableSpellCheck(fSpelling->IsMarked()); } break; + + case M_EDIT_QUERIES: + { + BPath path; + if (_GetQueryPath(&path) < B_OK) + break; + + // the user used this command, make sure the folder actually + // exists - if it didn't inform the user what to do with it + BEntry entry(path.Path()); + bool showAlert = false; + if (!entry.Exists()) { + showAlert = true; + create_directory(path.Path(), 0777); + } + + BEntry folderEntry; + if (folderEntry.SetTo(path.Path()) == B_OK + && folderEntry.Exists()) { + BMessage openFolderCommand(B_REFS_RECEIVED); + BMessenger tracker("application/x-vnd.Be-TRAK"); + + entry_ref ref; + folderEntry.GetRef(&ref); + openFolderCommand.AddRef("refs", &ref); + tracker.SendMessage(&openFolderCommand); + } + + if (showAlert) { + // just some patience before Tracker pops up the folder + snooze(250000); + BAlert* alert = new BAlert("helpful message", + "Place your favorite e-mail queries into your " + "this folder. These may also be templates.", + "Ok", NULL, NULL, B_WIDTH_AS_USUAL, B_IDEA_ALERT); + alert->Go(NULL); + } + + break; + } +#ifdef __HAIKU__ + case B_PATH_MONITOR: + _RebuildQueryMenu(); + break; +#endif default: BWindow::MessageReceived(msg); @@ -1611,6 +1680,10 @@ TMailWindow::QuitRequested() SetCurrentMessageRead(); } +#ifdef __HAIKU__ + BPrivate::BPathMonitor::StopWatching(BMessenger(this, this)); +#endif + return true; } @@ -2782,6 +2855,39 @@ TMailWindow::FrontmostWindow() } +/* +// Copied from src/kits/tracker/FindPanel.cpp. +uint32 +TMailWindow::InitialMode(const BNode *node) +{ + if (!node || node->InitCheck() != B_OK) + return kByNameItem; + + uint32 result; + if (node->ReadAttr(kAttrQueryInitialMode, B_INT32_TYPE, 0, + (int32 *)&result, sizeof(int32)) <= 0) + return kByNameItem; + + return result; +} + + +// Copied from src/kits/tracker/FindPanel.cpp. +int32 +TMailWindow::InitialAttrCount(const BNode *node) +{ + if (!node || node->InitCheck() != B_OK) + return 1; + + int32 result; + if (node->ReadAttr(kAttrQueryInitialNumAttrs, B_INT32_TYPE, 0, + &result, sizeof(int32)) <= 0) + return 1; + + return result; +}*/ + + // #pragma mark - @@ -2807,3 +2913,175 @@ TMailWindow::_UpdateSizeLimits() SetSizeLimits(minWidth, RIGHT_BOUNDARY, minHeight, RIGHT_BOUNDARY); } + + +status_t +TMailWindow::_GetQueryPath(BPath* queryPath) const +{ + // get the user home directory and from there the query folder + status_t ret = find_directory(B_USER_DIRECTORY, queryPath); + if (ret == B_OK) + ret = queryPath->Append(kQueriesDirectory); + + return ret; +} + + +void +TMailWindow::_RebuildQueryMenu(bool firstTime) +{ + while (BMenuItem* item = fQueryMenu->ItemAt(0L)) + delete item; + + fQueryMenu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE("Edit Queries...","???..."), + new BMessage(M_EDIT_QUERIES), 'E', B_SHIFT_KEY)); + + bool queryItemsAdded = false; + + BPath queryPath; + if (_GetQueryPath(&queryPath) < B_OK) + return; + + BDirectory queryDir(queryPath.Path()); + + if (firstTime) { +#ifdef __HAIKU__ + BPrivate::BPathMonitor::StartWatching(queryPath.Path(), + B_WATCH_RECURSIVELY, BMessenger(this, this)); +#endif + } + + // If we find the named query, add it to the menu. + BEntry entry; + while (queryDir.GetNextEntry(&entry) == B_OK) { + + char name[B_FILE_NAME_LENGTH + 1]; + entry.GetName(name); + + char* queryString = _BuildQueryString(&entry); + if (queryString == NULL) + continue; + + queryItemsAdded = true; + + QueryMenu* queryMenu = new QueryMenu(name, false); + queryMenu->SetTargetForItems(be_app); + queryMenu->SetPredicate(queryString); + fQueryMenu->AddItem(queryMenu); + + free(queryString); + } + + if (queryItemsAdded) + fQueryMenu->AddItem(new BSeparatorItem(), 1); +} + + +char* +TMailWindow::_BuildQueryString(BEntry* entry) const +{ + BNode node(entry); + if (node.InitCheck() != B_OK) + return NULL; + + uint32 mode; + if (node.ReadAttr(kAttrQueryInitialMode, B_INT32_TYPE, 0, (int32*)&mode, + sizeof(int32)) <= 0) { + mode = kByNameItem; + } + + BString queryString; + switch(mode) { + case kByForumlaItem: + { + BString buffer; + if (node.ReadAttrString(kAttrQueryInitialString, &buffer) == B_OK) + queryString << buffer; + break; + } + + case kByNameItem: + { + BString buffer; + if (node.ReadAttrString(kAttrQueryInitialString, &buffer) == B_OK) + queryString << "(name==*" << buffer << "*)"; + break; + } + + case kByAttributeItem: + { + int32 count = 1; + if (node.ReadAttr(kAttrQueryInitialNumAttrs, B_INT32_TYPE, 0, + (int32 *)&mode, sizeof(int32)) <= 0) { + count = 1; + } + + attr_info info; + if (node.GetAttrInfo(kAttrQueryInitialAttrs, &info) != B_OK) + break; + + if (count > 1 ) + queryString << "("; + + char *buffer = new char[info.size]; + if (node.ReadAttr(kAttrQueryInitialAttrs, B_MESSAGE_TYPE, 0, + buffer, (size_t)info.size) == info.size) { + BMessage message; + if (message.Unflatten(buffer) == B_OK) { + for (int32 index = 0; /*index < count*/; index++) { + + const char *field; + const char *value; + if (message.FindString("menuSelection", + index, &field) != B_OK + || message.FindString("attrViewText", + index, &value) != B_OK) { + break; + } + + // ignore the mime type, we'll force it to be email + // later + if (strcmp(field, "BEOS:TYPE") != 0) { + // TODO: check if subMenu contains the type of + // comparison we are suppose to make here + queryString << "(" << field << "==\"" + << value << "\")"; + + int32 logicMenuSelectedIndex; + if (message.FindInt32("logicalRelation", index, + &logicMenuSelectedIndex) == B_OK) { + if (logicMenuSelectedIndex == 0) + queryString << "&&"; + else if (logicMenuSelectedIndex == 1) + queryString << "||"; + } else + break; + } + } + } + } + + if (count > 1 ) + queryString << ")"; + + delete [] buffer; + break; + } + + default: + break; + } + + if (queryString.Length() == 0) + return NULL; + + // force it to check for email only + if (queryString.FindFirst("text/x-email") < 0 ) { + BString temp; + temp << "(" << queryString << "&&(BEOS:TYPE==\"text/x-email\"))"; + queryString = temp; + } + + return strdup(queryString.String()); +} + diff --git a/src/apps/mail/MailWindow.h b/src/apps/mail/MailWindow.h index d8f4abd816..bcb26f6b5d 100644 --- a/src/apps/mail/MailWindow.h +++ b/src/apps/mail/MailWindow.h @@ -121,6 +121,10 @@ class TMailWindow : public BWindow { private: void _UpdateSizeLimits(); + status_t _GetQueryPath(BPath* path) const; + void _RebuildQueryMenu(bool firstTime = false); + char* _BuildQueryString(BEntry* entry) const; + TMailApp* fApp; BEmailMessage* fMail; @@ -149,6 +153,8 @@ class TMailWindow : public BWindow { BMenuItem* fDeleteNext; BMenuItem* fSpelling; BMenu* fSaveAddrMenu; + + BMenu* fQueryMenu; ButtonBar* fButtonBar; BmapButton* fSendButton; @@ -161,6 +167,7 @@ class TMailWindow : public BWindow { THeaderView* fHeaderView; TEnclosuresView* fEnclosuresView; TMenu* fSignature; + BMessenger fTrackerMessenger; // Talks to tracker window that this was launched from. BMessenger fMessengerToSpamServer; diff --git a/src/apps/mail/Messages.h b/src/apps/mail/Messages.h index 498332de12..ebead67088 100644 --- a/src/apps/mail/Messages.h +++ b/src/apps/mail/Messages.h @@ -54,7 +54,7 @@ enum TEXT { }; enum MENUS { - /* app */ + // app M_NEW = SUBJECT_FIELD + 64, M_PREFS, M_EDIT_SIGNATURE, @@ -63,7 +63,8 @@ enum MENUS { M_SIZE, M_BEGINNER, M_EXPERT, - /* file */ + + // file M_REPLY, M_REPLY_TO_SENDER, M_REPLY_ALL, @@ -88,7 +89,8 @@ enum MENUS { M_STATUS, M_OPEN_MAIL_BOX, M_OPEN_MAIL_FOLDER, - /* edit */ + + // edit M_SELECT, M_QUOTE, M_REMOVE_QUOTE, @@ -98,16 +100,23 @@ enum MENUS { M_SIG_MENU, M_FIND, M_FIND_AGAIN, - /* encls */ + + // queries + M_EDIT_QUERIES, + M_EXECUTE_QUERY, + + // encls M_ADD, M_REMOVE, M_OPEN, M_COPY, - /* nav */ + + // nav M_NEXTMSG, M_PREVMSG, M_SAVE_POSITION, - /* Spam GUI button and menu items. Order is important. */ + + // Spam GUI button and menu items. Order is important. M_SPAM_BUTTON, M_TRAIN_SPAM_AND_DELETE, M_TRAIN_SPAM,