1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-12-24 08:38:51 -05:00

Make most important flags separate database columns

This is the first step to speed up searches and flag updates.
This commit is contained in:
cketti 2012-12-04 05:13:58 +01:00
parent d30cda26fb
commit c0b5255e24
9 changed files with 296 additions and 183 deletions

View File

@ -79,7 +79,8 @@ import com.fsck.k9.mail.store.StorageManager;
import com.fsck.k9.mail.store.WebDavStore;
import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.search.SearchAccount;
import com.fsck.k9.search.SearchModifier;
import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.Searchfield;
import com.fsck.k9.view.ColorChip;
import com.fsck.k9.preferences.SettingsExporter;
import com.fsck.k9.preferences.SettingsImportExportException;
@ -1695,8 +1696,8 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
holder.flaggedMessageCount.setText(Integer.toString(stats.flaggedMessageCount));
holder.flaggedMessageCountWrapper.setVisibility(stats.flaggedMessageCount > 0 ? View.VISIBLE : View.GONE);
holder.flaggedMessageCountWrapper.setOnClickListener(new AccountClickListener(account, SearchModifier.FLAGGED));
holder.newMessageCountWrapper.setOnClickListener(new AccountClickListener(account, SearchModifier.UNREAD));
holder.flaggedMessageCountWrapper.setOnClickListener(createFlaggedSearch(account));
holder.newMessageCountWrapper.setOnClickListener(createUnreadSearch(account));
view.getBackground().setAlpha(stats.available ? 0 : 127);
@ -1753,6 +1754,43 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
return view;
}
private OnClickListener createFlaggedSearch(BaseAccount account) {
String searchTitle = getString(R.string.search_title, account.getDescription(),
getString(R.string.flagged_modifier));
LocalSearch search;
if (account instanceof SearchAccount) {
search = ((SearchAccount) account).getRelatedSearch().clone();
search.setName(searchTitle);
} else {
search = new LocalSearch(searchTitle);
search.addAccountUuid(account.getUuid());
}
search.and(Searchfield.FLAGGED, "1", Attribute.EQUALS);
return new AccountClickListener(search);
}
private OnClickListener createUnreadSearch(BaseAccount account) {
String searchTitle = getString(R.string.search_title, account.getDescription(),
getString(R.string.unread_modifier));
LocalSearch search;
if (account instanceof SearchAccount) {
search = ((SearchAccount) account).getRelatedSearch().clone();
search.setName(searchTitle);
} else {
search = new LocalSearch(searchTitle);
search.addAccountUuid(account.getUuid());
}
search.and(Searchfield.READ, "1", Attribute.NOT_EQUALS);
return new AccountClickListener(search);
}
class AccountViewHolder {
public TextView description;
public TextView email;
@ -1783,27 +1821,14 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private class AccountClickListener implements OnClickListener {
final BaseAccount account;
final SearchModifier searchModifier;
AccountClickListener(BaseAccount nAccount, SearchModifier nSearchModifier) {
account = nAccount;
searchModifier = nSearchModifier;
final LocalSearch search;
AccountClickListener(LocalSearch search) {
this.search = search;
}
@Override
public void onClick(View v) {
final String description = getString(R.string.search_title, account.getDescription(), getString(searchModifier.resId));
LocalSearch search = null;
if (account instanceof SearchAccount) {
search = ((SearchAccount) account).getRelatedSearch().clone();
search.setName(description);
} else {
search = new LocalSearch(description);
search.addAccountUuid(account.getUuid());
}
search.allRequiredFlags(searchModifier.requiredFlags);
search.allForbiddenFlags(searchModifier.forbiddenFlags);
MessageList.actionDisplaySearch(Accounts.this, search, true, false);
}

View File

@ -62,14 +62,13 @@ import com.fsck.k9.controller.MessagingListener;
import com.fsck.k9.helper.SizeFormatter;
import com.fsck.k9.helper.power.TracingPowerManager;
import com.fsck.k9.helper.power.TracingPowerManager.TracingWakeLock;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
import com.fsck.k9.search.LocalSearch;
import com.fsck.k9.search.SearchModifier;
import com.fsck.k9.search.SearchSpecification;
import com.fsck.k9.search.SearchSpecification.Attribute;
import com.fsck.k9.search.SearchSpecification.Searchfield;
import com.fsck.k9.service.MailService;
/**
@ -1118,7 +1117,8 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
if (folder.unreadMessageCount != 0) {
holder.newMessageCount.setText(Integer
.toString(folder.unreadMessageCount));
holder.newMessageCountWrapper.setOnClickListener(new FolderClickListener(mAccount, folder.name, folder.displayName, SearchModifier.UNREAD));
holder.newMessageCountWrapper.setOnClickListener(
createUnreadSearch(mAccount, folder));
holder.newMessageCountWrapper.setVisibility(View.VISIBLE);
holder.newMessageCountIcon.setBackgroundDrawable( mAccount.generateColorChip(false, false, false, false, false).drawable() );
} else {
@ -1128,7 +1128,8 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
if (folder.flaggedMessageCount > 0) {
holder.flaggedMessageCount.setText(Integer
.toString(folder.flaggedMessageCount));
holder.flaggedMessageCountWrapper.setOnClickListener(new FolderClickListener(mAccount, folder.name, folder.displayName, SearchModifier.FLAGGED));
holder.flaggedMessageCountWrapper.setOnClickListener(
createFlaggedSearch(mAccount, folder));
holder.flaggedMessageCountWrapper.setVisibility(View.VISIBLE);
holder.flaggedMessageCountIcon.setBackgroundDrawable( mAccount.generateColorChip(false, false, false, false,true).drawable() );
} else {
@ -1152,6 +1153,36 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
return view;
}
private OnClickListener createFlaggedSearch(Account account, FolderInfoHolder folder) {
String searchTitle = getString(R.string.search_title,
getString(R.string.message_list_title, account.getDescription(),
folder.displayName),
getString(R.string.flagged_modifier));
LocalSearch search = new LocalSearch(searchTitle);
search.and(Searchfield.FLAGGED, "1", Attribute.EQUALS);
search.addAllowedFolder(folder.name);
search.addAccountUuid(account.getUuid());
return new FolderClickListener(search);
}
private OnClickListener createUnreadSearch(Account account, FolderInfoHolder folder) {
String searchTitle = getString(R.string.search_title,
getString(R.string.message_list_title, account.getDescription(),
folder.displayName),
getString(R.string.unread_modifier));
LocalSearch search = new LocalSearch(searchTitle);
search.and(Searchfield.READ, "1", Attribute.NOT_EQUALS);
search.addAllowedFolder(folder.name);
search.addAccountUuid(account.getUuid());
return new FolderClickListener(search);
}
@Override
public boolean hasStableIds() {
return true;
@ -1260,32 +1291,14 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
private class FolderClickListener implements OnClickListener {
final BaseAccount account;
final String folderName;
final String displayName;
final SearchModifier searchModifier;
FolderClickListener(BaseAccount nAccount, String folderName, String displayName, SearchModifier nSearchModifier) {
account = nAccount;
this.folderName = folderName;
searchModifier = nSearchModifier;
this.displayName = displayName;
final LocalSearch search;
FolderClickListener(LocalSearch search) {
this.search = search;
}
@Override
public void onClick(View v) {
final String description = getString(R.string.search_title,
getString(R.string.message_list_title, account.getDescription(), displayName),
getString(searchModifier.resId));
LocalSearch search = new LocalSearch(description);
try {
search.allRequiredFlags(searchModifier.requiredFlags);
search.allForbiddenFlags(searchModifier.forbiddenFlags);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
search.addAllowedFolder(folderName);
search.addAccountUuid(account.getUuid());
MessageList.actionDisplaySearch(FolderList.this, search, true, false);
}
}
@ -1294,7 +1307,7 @@ public class FolderList extends K9ListActivity implements OnNavigationListener {
String description = getString(R.string.search_title, mAccount.getDescription(), getString(R.string.unread_modifier));
LocalSearch search = new LocalSearch(description);
search.addAccountUuid(account.getUuid());
search.allForbiddenFlags(new Flag[] { Flag.SEEN });
search.and(Searchfield.READ, "1", Attribute.NOT_EQUALS);
MessageList.actionDisplaySearch(context, search, true, false);
}

View File

@ -110,7 +110,10 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
MessageColumns.SENDER_LIST,
MessageColumns.TO_LIST,
MessageColumns.CC_LIST,
MessageColumns.FLAGS,
MessageColumns.READ,
MessageColumns.FLAGGED,
MessageColumns.ANSWERED,
MessageColumns.FORWARDED,
MessageColumns.ATTACHMENT_COUNT,
MessageColumns.FOLDER_ID,
MessageColumns.PREVIEW,
@ -129,14 +132,17 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
private static final int SENDER_LIST_COLUMN = 5;
private static final int TO_LIST_COLUMN = 6;
private static final int CC_LIST_COLUMN = 7;
private static final int FLAGS_COLUMN = 8;
private static final int ATTACHMENT_COUNT_COLUMN = 9;
private static final int FOLDER_ID_COLUMN = 10;
private static final int PREVIEW_COLUMN = 11;
private static final int THREAD_ROOT_COLUMN = 12;
private static final int ACCOUNT_UUID_COLUMN = 13;
private static final int FOLDER_NAME_COLUMN = 14;
private static final int THREAD_COUNT_COLUMN = 15;
private static final int READ_COLUMN = 8;
private static final int FLAGGED_COLUMN = 9;
private static final int ANSWERED_COLUMN = 10;
private static final int FORWARDED_COLUMN = 11;
private static final int ATTACHMENT_COUNT_COLUMN = 12;
private static final int FOLDER_ID_COLUMN = 13;
private static final int PREVIEW_COLUMN = 14;
private static final int THREAD_ROOT_COLUMN = 15;
private static final int ACCOUNT_UUID_COLUMN = 16;
private static final int FOLDER_NAME_COLUMN = 17;
private static final int THREAD_COUNT_COLUMN = 18;
private static final String[] PROJECTION = Utility.copyOf(THREADED_PROJECTION,
THREAD_COUNT_COLUMN);
@ -232,8 +238,8 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
@Override
public int compare(Cursor cursor1, Cursor cursor2) {
int o1IsFlagged = (cursor1.getString(FLAGS_COLUMN).contains("FLAGGED")) ? 0 : 1;
int o2IsFlagged = (cursor2.getString(FLAGS_COLUMN).contains("FLAGGED")) ? 0 : 1;
int o1IsFlagged = (cursor1.getInt(FLAGGED_COLUMN) == 1) ? 0 : 1;
int o2IsFlagged = (cursor2.getInt(FLAGGED_COLUMN) == 1) ? 0 : 1;
return o1IsFlagged - o2IsFlagged;
}
}
@ -242,8 +248,8 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
@Override
public int compare(Cursor cursor1, Cursor cursor2) {
int o1IsUnread = (cursor1.getString(FLAGS_COLUMN).contains("SEEN")) ? 1 : 0;
int o2IsUnread = (cursor2.getString(FLAGS_COLUMN).contains("SEEN")) ? 1 : 0;
int o1IsUnread = cursor1.getInt(READ_COLUMN);
int o2IsUnread = cursor2.getInt(READ_COLUMN);
return o1IsUnread - o2IsUnread;
}
}
@ -1345,27 +1351,8 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
Account account = getAccountFromCursor(cursor);
String subject = cursor.getString(SUBJECT_COLUMN);
String flagList = cursor.getString(FLAGS_COLUMN);
String[] flags = flagList.split(",");
boolean read = false;
boolean flagged = false;
for (int i = 0, len = flags.length; i < len; i++) {
try {
switch (Flag.valueOf(flags[i])) {
case SEEN: {
read = true;
break;
}
case FLAGGED: {
flagged = true;
break;
}
default: {
// We don't care about the other flags
}
}
} catch (Exception e) { /* ignore */ }
}
boolean read = (cursor.getInt(READ_COLUMN) == 1);
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
menu.setHeaderTitle(subject);
@ -1637,37 +1624,10 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
int threadCount = (mThreadedList) ? cursor.getInt(THREAD_COUNT_COLUMN) : 0;
String flagList = cursor.getString(FLAGS_COLUMN);
String[] flags = flagList.split(",");
boolean read = false;
boolean flagged = false;
boolean answered = false;
boolean forwarded = false;
for (int i = 0, len = flags.length; i < len; i++) {
try {
switch (Flag.valueOf(flags[i])) {
case SEEN: {
read = true;
break;
}
case FLAGGED: {
flagged = true;
break;
}
case ANSWERED: {
answered = true;
break;
}
case FORWARDED: {
forwarded = true;
break;
}
default: {
// We don't care about the other flags
}
}
} catch (Exception e) { /* ignore */ }
}
boolean read = (cursor.getInt(READ_COLUMN) == 1);
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
boolean answered = (cursor.getInt(ANSWERED_COLUMN) == 1);
boolean forwarded = (cursor.getInt(FORWARDED_COLUMN) == 1);
boolean hasAttachments = (cursor.getInt(ATTACHMENT_COUNT_COLUMN) > 0);
@ -1988,12 +1948,13 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
long uniqueId = cursor.getLong(mUniqueIdColumn);
if (mSelected.contains(uniqueId)) {
String flags = cursor.getString(FLAGS_COLUMN);
boolean read = (cursor.getInt(READ_COLUMN) == 1);
boolean flagged = (cursor.getInt(FLAGGED_COLUMN) == 1);
if (!flags.contains(Flag.FLAGGED.name())) {
if (!flagged) {
isBatchFlag = true;
}
if (!flags.contains(Flag.SEEN.name())) {
if (!read) {
isBatchRead = true;
}
@ -2834,7 +2795,7 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
break;
}
case SORT_FLAGGED: {
sortColumn = "(" + MessageColumns.FLAGS + " NOT LIKE '%FLAGGED%')";
sortColumn = "(" + MessageColumns.FLAGGED + " != 1)";
break;
}
// case SORT_SENDER: {
@ -2847,7 +2808,7 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
break;
}
case SORT_UNREAD: {
sortColumn = "(" + MessageColumns.FLAGS + " LIKE '%SEEN%')";
sortColumn = MessageColumns.READ;
break;
}
case SORT_DATE:
@ -2894,6 +2855,8 @@ public class MessageListFragment extends SherlockFragment implements OnItemClick
cleanupSelected(cursor);
mAdapter.swapCursor(cursor);
computeBatchDirection();
}
private void cleanupSelected(Cursor cursor) {

View File

@ -98,7 +98,7 @@ public class LocalStore extends Store implements Serializable {
*/
static private String GET_MESSAGES_COLS =
"subject, sender_list, date, uid, flags, messages.id, to_list, cc_list, "
+ "bcc_list, reply_to_list, attachment_count, internal_date, message_id, folder_id, preview, thread_root, thread_parent ";
+ "bcc_list, reply_to_list, attachment_count, internal_date, message_id, folder_id, preview, thread_root, thread_parent, deleted, read, flagged, answered, forwarded ";
static private String GET_FOLDER_COLS = "id, name, unread_count, visible_limit, last_updated, status, push_state, last_pushed, flagged_count, integrate, top_group, poll_class, push_class, display_class";
@ -111,7 +111,7 @@ public class LocalStore extends Store implements Serializable {
*/
private static final int UID_CHECK_BATCH_SIZE = 500;
public static final int DB_VERSION = 45;
public static final int DB_VERSION = 46;
protected String uUid = null;
@ -201,7 +201,11 @@ public class LocalStore extends Store implements Serializable {
"thread_root INTEGER, " +
"thread_parent INTEGER, " +
"normalized_subject_hash INTEGER, " +
"empty INTEGER" +
"empty INTEGER, " +
"read INTEGER default 0, " +
"flagged INTEGER default 0, " +
"answered INTEGER default 0, " +
"forwarded INTEGER default 0" +
")");
db.execSQL("DROP TABLE IF EXISTS headers");
@ -222,6 +226,12 @@ public class LocalStore extends Store implements Serializable {
db.execSQL("DROP INDEX IF EXISTS msg_thread_parent");
db.execSQL("CREATE INDEX IF NOT EXISTS msg_thread_parent ON messages (thread_parent)");
db.execSQL("DROP INDEX IF EXISTS msg_read");
db.execSQL("CREATE INDEX IF NOT EXISTS msg_read ON messages (read)");
db.execSQL("DROP INDEX IF EXISTS msg_flagged");
db.execSQL("CREATE INDEX IF NOT EXISTS msg_flagged ON messages (flagged)");
db.execSQL("DROP TABLE IF EXISTS attachments");
db.execSQL("CREATE TABLE attachments (id INTEGER PRIMARY KEY, message_id INTEGER,"
+ "store_data TEXT, content_uri TEXT, size INTEGER, name TEXT,"
@ -435,6 +445,94 @@ public class LocalStore extends Store implements Serializable {
}
}
}
if (db.getVersion() < 46) {
db.execSQL("ALTER TABLE messages ADD read INTEGER default 0");
db.execSQL("ALTER TABLE messages ADD flagged INTEGER default 0");
db.execSQL("ALTER TABLE messages ADD answered INTEGER default 0");
db.execSQL("ALTER TABLE messages ADD forwarded INTEGER default 0");
String[] projection = { "id", "flags" };
ContentValues cv = new ContentValues();
List<Flag> extraFlags = new ArrayList<Flag>();
Cursor cursor = db.query("messages", projection, null, null, null, null, null);
try {
while (cursor.moveToNext()) {
long id = cursor.getLong(0);
String flagList = cursor.getString(1);
boolean read = false;
boolean flagged = false;
boolean answered = false;
boolean forwarded = false;
if (flagList != null && flagList.length() > 0) {
String[] flags = flagList.split(",");
for (String flagStr : flags) {
try {
Flag flag = Flag.valueOf(flagStr);
switch (flag) {
case ANSWERED: {
answered = true;
break;
}
case DELETED: {
// Don't store this in column 'flags'
break;
}
case FLAGGED: {
flagged = true;
break;
}
case FORWARDED: {
forwarded = true;
break;
}
case SEEN: {
read = true;
break;
}
case DRAFT:
case RECENT:
case X_DESTROYED:
case X_DOWNLOADED_FULL:
case X_DOWNLOADED_PARTIAL:
case X_GOT_ALL_HEADERS:
case X_REMOTE_COPY_STARTED:
case X_SEND_FAILED:
case X_SEND_IN_PROGRESS: {
extraFlags.add(flag);
break;
}
}
} catch (Exception e) {
// Ignore bad flags
}
}
}
cv.put("flags", serializeFlags(extraFlags.toArray(EMPTY_FLAG_ARRAY)));
cv.put("read", read);
cv.put("flagged", flagged);
cv.put("answered", answered);
cv.put("forwarded", forwarded);
db.update("messages", cv, "id = ?", new String[] { Long.toString(id) });
cv.clear();
extraFlags.clear();
}
} finally {
cursor.close();
}
db.execSQL("CREATE INDEX IF NOT EXISTS msg_read ON messages (read)");
db.execSQL("CREATE INDEX IF NOT EXISTS msg_flagged ON messages (flagged)");
}
}
} catch (SQLiteException e) {
Log.e(K9.LOG_TAG, "Exception while upgrading database. Resetting the DB to v0");
@ -1148,6 +1246,28 @@ public class LocalStore extends Store implements Serializable {
});
}
private String serializeFlags(Flag[] flags) {
List<Flag> extraFlags = new ArrayList<Flag>();
for (Flag flag : flags) {
switch (flag) {
case DELETED:
case SEEN:
case FLAGGED:
case ANSWERED:
case FORWARDED: {
break;
}
default: {
extraFlags.add(flag);
}
}
}
return Utility.combine(extraFlags.toArray(EMPTY_FLAG_ARRAY), ',').toUpperCase(Locale.US);
}
public class LocalFolder extends Folder implements Serializable {
/**
*
@ -2089,7 +2209,8 @@ public class LocalStore extends Store implements Serializable {
cv.clear();
cv.put("uid", oldUID);
cv.put("flags", serializeFlags(new Flag[] { Flag.DELETED, Flag.SEEN }));
cv.putNull("flags");
cv.put("read", 1);
cv.put("deleted", 1);
cv.put("folder_id", mFolderId);
@ -2401,6 +2522,10 @@ public class LocalStore extends Store implements Serializable {
? System.currentTimeMillis() : message.getSentDate().getTime());
cv.put("flags", serializeFlags(message.getFlags()));
cv.put("deleted", message.isSet(Flag.DELETED) ? 1 : 0);
cv.put("read", message.isSet(Flag.SEEN) ? 1 : 0);
cv.put("flagged", message.isSet(Flag.FLAGGED) ? 1 : 0);
cv.put("answered", message.isSet(Flag.ANSWERED) ? 1 : 0);
cv.put("forwarded", message.isSet(Flag.FORWARDED) ? 1 : 0);
cv.put("folder_id", mFolderId);
cv.put("to_list", Address.pack(message.getRecipients(RecipientType.TO)));
cv.put("cc_list", Address.pack(message.getRecipients(RecipientType.CC)));
@ -2497,7 +2622,8 @@ public class LocalStore extends Store implements Serializable {
+ "uid = ?, subject = ?, sender_list = ?, date = ?, flags = ?, "
+ "folder_id = ?, to_list = ?, cc_list = ?, bcc_list = ?, "
+ "html_content = ?, text_content = ?, preview = ?, reply_to_list = ?, "
+ "attachment_count = ? WHERE id = ?",
+ "attachment_count = ?, read = ?, flagged = ?, answered = ?, forwarded = ? "
+ "WHERE id = ?",
new Object[] {
message.getUid(),
message.getSubject(),
@ -2518,6 +2644,10 @@ public class LocalStore extends Store implements Serializable {
preview.length() > 0 ? preview : null,
Address.pack(message.getReplyTo()),
attachments.size(),
message.isSet(Flag.SEEN) ? 1 : 0,
message.isSet(Flag.FLAGGED) ? 1 : 0,
message.isSet(Flag.ANSWERED) ? 1 : 0,
message.isSet(Flag.FORWARDED) ? 1 : 0,
message.mId
});
@ -3145,10 +3275,6 @@ public class LocalStore extends Store implements Serializable {
});
}
private String serializeFlags(Flag[] flags) {
return Utility.combine(flags, ',').toUpperCase(Locale.US);
}
private ThreadInfo doMessageThreading(SQLiteDatabase db, Message message)
throws MessagingException {
long rootId = -1;
@ -3402,6 +3528,18 @@ public class LocalStore extends Store implements Serializable {
mRootId = (cursor.isNull(15)) ? -1 : cursor.getLong(15);
mParentId = (cursor.isNull(16)) ? -1 : cursor.getLong(16);
boolean deleted = (cursor.getInt(17) == 1);
boolean read = (cursor.getInt(18) == 1);
boolean flagged = (cursor.getInt(19) == 1);
boolean answered = (cursor.getInt(20) == 1);
boolean forwarded = (cursor.getInt(21) == 1);
setFlagInternal(Flag.DELETED, deleted);
setFlagInternal(Flag.SEEN, read);
setFlagInternal(Flag.FLAGGED, flagged);
setFlagInternal(Flag.ANSWERED, answered);
setFlagInternal(Flag.FORWARDED, forwarded);
}
/**
@ -3571,8 +3709,15 @@ public class LocalStore extends Store implements Serializable {
/*
* Set the flags on the message.
*/
db.execSQL("UPDATE messages " + "SET flags = ? " + " WHERE id = ?", new Object[]
{ Utility.combine(getFlags(), ',').toUpperCase(Locale.US), mId });
ContentValues cv = new ContentValues();
cv.put("flags", serializeFlags(getFlags()));
cv.put("read", isSet(Flag.SEEN) ? 1 : 0);
cv.put("flagged", isSet(Flag.FLAGGED) ? 1 : 0);
cv.put("answered", isSet(Flag.ANSWERED) ? 1 : 0);
cv.put("forwarded", isSet(Flag.FORWARDED) ? 1 : 0);
db.update("messages", cv, "id = ?", new String[] { Long.toString(mId) });
return null;
}
});

View File

@ -77,6 +77,10 @@ public class EmailProvider extends ContentProvider {
MessageColumns.PREVIEW,
MessageColumns.THREAD_ROOT,
MessageColumns.THREAD_PARENT,
MessageColumns.READ,
MessageColumns.FLAGGED,
MessageColumns.ANSWERED,
MessageColumns.FORWARDED,
InternalMessageColumns.DELETED,
InternalMessageColumns.EMPTY,
InternalMessageColumns.TEXT_CONTENT,
@ -118,6 +122,10 @@ public class EmailProvider extends ContentProvider {
public static final String THREAD_ROOT = "thread_root";
public static final String THREAD_PARENT = "thread_parent";
public static final String THREAD_COUNT = "thread_count";
public static final String READ = "read";
public static final String FLAGGED = "flagged";
public static final String ANSWERED = "answered";
public static final String FORWARDED = "forwarded";
}
private interface InternalMessageColumns extends MessageColumns {

View File

@ -229,34 +229,6 @@ public class LocalSearch implements SearchSpecification {
return mConditions;
}
/**
* Add all the flags to this node as required flags. The
* provided flags will be combined using AND with the root.
*
* @param requiredFlags Array of required flags.
*/
public void allRequiredFlags(Flag[] requiredFlags) {
if (requiredFlags != null) {
for (Flag f : requiredFlags) {
and(new SearchCondition(Searchfield.FLAG, Attribute.CONTAINS, f.name()));
}
}
}
/**
* Add all the flags to this node as forbidden flags. The
* provided flags will be combined using AND with the root.
*
* @param forbiddenFlags Array of forbidden flags.
*/
public void allForbiddenFlags(Flag[] forbiddenFlags) {
if (forbiddenFlags != null) {
for (Flag f : forbiddenFlags) {
and(new SearchCondition(Searchfield.FLAG, Attribute.NOT_CONTAINS, f.name()));
}
}
}
/**
* TODO
* FOR NOW: And the folder with the root.

View File

@ -1,23 +0,0 @@
package com.fsck.k9.search;
import com.fsck.k9.R;
import com.fsck.k9.mail.Flag;
/**
* This enum represents filtering parameters used by {@link com.fsck.k9.search.SearchAccount}.
*/
public enum SearchModifier {
FLAGGED(R.string.flagged_modifier, new Flag[] { Flag.FLAGGED }, null),
UNREAD(R.string.unread_modifier, null, new Flag[] { Flag.SEEN });
public final int resId;
public final Flag[] requiredFlags;
public final Flag[] forbiddenFlags;
SearchModifier(int nResId, Flag[] nRequiredFlags, Flag[] nForbiddenFlags) {
resId = nResId;
requiredFlags = nRequiredFlags;
forbiddenFlags = nForbiddenFlags;
}
}

View File

@ -78,7 +78,9 @@ public interface SearchSpecification extends Parcelable {
DELETED,
THREAD_ROOT,
ID,
INTEGRATE
INTEGRATE,
READ,
FLAGGED
}

View File

@ -136,6 +136,14 @@ public class SqlQueryBuilder {
columnName = "integrate";
break;
}
case READ: {
columnName = "read";
break;
}
case FLAGGED: {
columnName = "flagged";
break;
}
}
if (columnName == null) {