patch by "anxiety":

* added a Query menu to the main menu, giving access to some
  email queries
I refactored the patch a little and added monitoring the query folder,
so that all open Mail windows should update. However, I might not have
got it to work as intended, at least I got no entries for the query results,
even though the same query did return results when run in Tracker.

This should implement the idea in #1208, and that's also where the patch
was attached. 


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22702 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2007-10-24 23:01:54 +00:00
parent cc9ad8e824
commit 5913d84eb8
4 changed files with 306 additions and 11 deletions

View File

@ -10,6 +10,7 @@ if $(TARGET_PLATFORM) != haiku {
UsePrivateHeaders mail ;
UsePrivateHeaders textencoding ;
UsePrivateHeaders shared ;
UsePrivateHeaders storage ;
AddResources Mail : Mail.rdef pictures.rdef ;
Application Mail :

View File

@ -48,6 +48,9 @@ All rights reserved.
#include <Debug.h>
#include <E-mail.h>
#include <InterfaceKit.h>
#ifdef __HAIKU__
# include <PathMonitor.h>
#endif
#include <Roster.h>
#include <Screen.h>
#include <StorageKit.h>
@ -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());
}

View File

@ -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;

View File

@ -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,