Mail: Add queries for same subject, sender, recipient

In the "Queries" menu, add three items at the top to start a query
for the same recipient/sender/subject as the current email. Move the
separator and "Edit queries..." item to the bottom of the menu.

The temporarily created queries are put into B_USER_CACHE_DIRECTORY/Mail/.
The data in those queries might be private, therefore not in system /tmp.

The queries use the DefaultQueryTemplates for x-email, if that exists. This
is done by copying all the template's attributes. Code for that borrowed from
'copyattr'.

When creating a query for the same subject, use the MAIL:thread text for
the search, as that doesn't contain stuff like "Re: Re: Fwd: Re...". Do
the query for MAIL:subject though, because sent emails don't have a
MAIL:thread attribute.

Change-Id: I23b46f3ec07760d17b076d8b8aa8839c5f88963f
Reviewed-on: https://review.haiku-os.org/768
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Humdinger 2018-12-10 18:00:12 +01:00 committed by waddlesplash
parent 5e621d3edd
commit 947124d152
3 changed files with 117 additions and 5 deletions

View File

@ -41,6 +41,7 @@ of their respective holders. All rights reserved.
#include <strings.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <syslog.h>
#include <unistd.h>
#include <AppFileInfo.h>
@ -79,6 +80,7 @@ of their respective holders. All rights reserved.
#include <CharacterSetRoster.h>
#include "AttributeUtilities.h"
#include "Content.h"
#include "Enclosures.h"
#include "FieldMsg.h"
@ -146,6 +148,11 @@ 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 const int kCopyBufferSize = 64 * 1024; // 64 KB
static const char* kSameRecipientItem = B_TRANSLATE_MARK("Same recipient");
static const char* kSameSenderItem = B_TRANSLATE_MARK("Same sender");
static const char* kSameSubjectItem = B_TRANSLATE_MARK("Same subject");
// static bitmap cache
@ -1670,6 +1677,41 @@ TMailWindow::MessageReceived(BMessage* msg)
}
break;
case M_QUERY_RECIPIENT:
{
BString searchText(fHeaderView->To());
if (searchText != "") {
_LaunchQuery(kSameRecipientItem, B_MAIL_ATTR_TO,
searchText);
}
break;
}
case M_QUERY_SENDER:
{
BString searchText(fHeaderView->From());
if (searchText != "") {
_LaunchQuery(kSameSenderItem, B_MAIL_ATTR_FROM,
searchText);
}
break;
}
case M_QUERY_SUBJECT:
{
// If there's no thread attribute (e.g. new mail) use subject
BString searchText(fHeaderView->Subject());
BNode node(fRef);
if (node.InitCheck() == B_OK)
node.ReadAttrString(B_MAIL_ATTR_THREAD, &searchText);
if (searchText != "") {
// query for subject as sent mails have no thread attribute
_LaunchQuery(kSameSubjectItem, B_MAIL_ATTR_SUBJECT,
searchText);
}
break;
}
case M_EDIT_QUERIES:
{
BPath path;
@ -3032,9 +3074,12 @@ TMailWindow::_RebuildQueryMenu(bool firstTime)
delete item;
}
fQueryMenu->AddItem(new BMenuItem(B_TRANSLATE("Edit queries"
B_UTF8_ELLIPSIS),
new BMessage(M_EDIT_QUERIES), 'E', B_SHIFT_KEY));
fQueryMenu->AddItem(new BMenuItem(kSameRecipientItem,
new BMessage(M_QUERY_RECIPIENT)));
fQueryMenu->AddItem(new BMenuItem(kSameSenderItem,
new BMessage(M_QUERY_SENDER)));
fQueryMenu->AddItem(new BMenuItem(kSameSubjectItem,
new BMessage(M_QUERY_SUBJECT)));
bool queryItemsAdded = false;
@ -3069,8 +3114,11 @@ TMailWindow::_RebuildQueryMenu(bool firstTime)
free(queryString);
}
if (queryItemsAdded)
fQueryMenu->AddItem(new BSeparatorItem(), 1);
fQueryMenu->AddItem(new BSeparatorItem());
fQueryMenu->AddItem(new BMenuItem(B_TRANSLATE("Edit queries"
B_UTF8_ELLIPSIS),
new BMessage(M_EDIT_QUERIES), 'E', B_SHIFT_KEY));
}
@ -3182,6 +3230,65 @@ TMailWindow::_BuildQueryString(BEntry* entry) const
}
void
TMailWindow::_LaunchQuery(const char* title, const char* attribute,
BString text)
{
/* ToDo:
If the search attribute is To or From, it'd be nice to parse the
search text to separate the email address and user name.
Then search for 'name || address' to get all mails of people,
never mind the account or mail config they sent from.
*/
text.ReplaceAll(" ", "*"); // query on MAIL:track demands * for space
text.ReplaceAll("\"", "\\\"");
BString* term = new BString("((");
term->Append(attribute);
term->Append("==\"*");
term->Append(text);
term->Append("*\")&&(BEOS:TYPE==\"text/x-email\"))");
BPath queryPath;
if (find_directory(B_USER_CACHE_DIRECTORY, &queryPath) != B_OK)
return;
queryPath.Append("Mail");
if ((create_directory(queryPath.Path(), 0777)) != B_OK)
return;
queryPath.Append(title);
BFile query(queryPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
if (query.InitCheck() != B_OK)
return;
BNode queryNode(queryPath.Path());
if (queryNode.InitCheck() != B_OK)
return;
// Copy layout from DefaultQueryTemplates
BPath templatePath;
find_directory(B_USER_SETTINGS_DIRECTORY, &templatePath);
templatePath.Append("Tracker/DefaultQueryTemplates/text_x-email");
BNode templateNode(templatePath.Path());
if (templateNode.InitCheck() == B_OK) {
if (CopyAttributes(templateNode, queryNode) != B_OK) {
syslog(LOG_INFO, "Mail: copying x-email DefaultQueryTemplate "
"attributes failed");
}
}
queryNode.WriteAttrString("_trk/qrystr", term);
BNodeInfo nodeInfo(&queryNode);
nodeInfo.SetType("application/x-vnd.Be-query");
// Launch query
BEntry entry(queryPath.Path());
entry_ref ref;
if (entry.GetRef(&ref) == B_OK)
be_roster->Launch(&ref);
}
void
TMailWindow::_AddReadButton()
{

View File

@ -127,6 +127,8 @@ private:
status_t _GetQueryPath(BPath* path) const;
void _RebuildQueryMenu(bool firstTime = false);
char* _BuildQueryString(BEntry* entry) const;
void _LaunchQuery(const char* title,
const char* attribute, BString text);
void _AddReadButton();
void _UpdateReadButton();

View File

@ -103,6 +103,9 @@ enum MENUS {
// queries
M_EDIT_QUERIES,
M_EXECUTE_QUERY,
M_QUERY_RECIPIENT,
M_QUERY_SENDER,
M_QUERY_SUBJECT,
// encls
M_ADD,