Merge pull request #1444 from JulienMasson/threads-sorting

mu: add an option to ignore leader when sorting childs of a thread
This commit is contained in:
Dirk-Jan C. Binnema 2020-02-10 21:58:33 +02:00 committed by GitHub
commit b77b536d81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 69 deletions

View File

@ -353,36 +353,8 @@ container_cmp (MuContainer *a, MuContainer *b, MuMsgFieldId mfid)
return mu_msg_cmp (a->msg, b->msg, mfid);
}
static gboolean
container_is_leaf (const MuContainer *c)
{
return c->child == NULL;
}
static MuContainer*
container_max (MuContainer *a, MuContainer *b, MuMsgFieldId mfid)
{
return container_cmp (a, b, mfid) > 0 ? a : b;
}
static MuContainer*
find_sorted_tree_leader (MuContainer *root, SortFuncData *order)
{
MuContainer *last_child;
if (container_is_leaf (root))
return root;
if (!order->descending)
last_child = root->child->last;
else /* reversed order, first is last */
last_child = root->child;
return container_max (root, last_child->leader, order->mfid);
}
static int
sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data)
sort_func_root (MuContainer *a, MuContainer *b, SortFuncData *data)
{
if (data->descending)
return container_cmp (b->leader, a->leader, data->mfid);
@ -390,10 +362,56 @@ sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data)
return container_cmp (a->leader, b->leader, data->mfid);
}
static int
sort_func_child (MuContainer *a, MuContainer *b, SortFuncData *data)
{
if (data->descending)
return container_cmp (a, b, data->mfid);
else
return container_cmp (b, a, data->mfid);
}
static MuContainer*
container_sort_real (MuContainer *c, SortFuncData *sfdata)
container_sort(MuContainer *c, GCompareDataFunc func, SortFuncData *sfdata)
{
GSList *lst;
lst = mu_container_to_list (c);
lst = g_slist_sort_with_data (lst, func, sfdata);
c = mu_container_from_list (lst);
g_slist_free (lst);
return c;
}
static MuContainer*
container_sort_child (MuContainer *c, SortFuncData *sfdata)
{
MuContainer *cur, *leader;
if (!c)
return NULL;
/* find leader */
leader = c->leader;
for (cur = c; cur; cur = cur->next) {
if (cur->child)
cur->child = container_sort_child (cur->child, sfdata);
if (container_cmp (cur->leader, leader, sfdata->mfid) > 0)
leader = cur->leader;
}
c = container_sort(c, (GCompareDataFunc)sort_func_child, sfdata);
/* set parent's leader to the one found */
c->parent->leader = leader;
return c;
}
static MuContainer*
container_sort_root (MuContainer *c, SortFuncData *sfdata)
{
MuContainer *cur;
if (!c)
@ -401,19 +419,10 @@ container_sort_real (MuContainer *c, SortFuncData *sfdata)
for (cur = c; cur; cur = cur->next) {
if (cur->child)
cur->child = container_sort_real (cur->child, sfdata);
cur->leader = find_sorted_tree_leader (cur, sfdata);
cur->child = container_sort_child (cur->child, sfdata);
}
/* sort siblings */
lst = mu_container_to_list (c);
lst = g_slist_sort_with_data(lst,
(GCompareDataFunc)sort_func_wrapper,
sfdata);
c = mu_container_from_list (lst);
g_slist_free (lst);
return c;
return container_sort (c, (GCompareDataFunc)sort_func_root, sfdata);
}
MuContainer*
@ -429,7 +438,7 @@ mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gboolean descending,
g_return_val_if_fail (c, NULL);
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL);
return container_sort_real (c, &sfdata);
return container_sort_root (c, &sfdata);
}

View File

@ -158,9 +158,9 @@ test_mu_threads_01 (void)
const tinfo items [] = {
{"0", "root0@msg.id", "root0"},
{"0:0", "child0.0@msg.id", "Re: child 0.0"},
{"0:1", "child0.1@msg.id", "Re: child 0.1"},
{"0:1:0", "child0.1.0@msg.id", "Re: child 0.1.0"},
{"0:0", "child0.1@msg.id", "Re: child 0.1"},
{"0:0:0", "child0.1.0@msg.id", "Re: child 0.1.0"},
{"0:1", "child0.0@msg.id", "Re: child 0.0"},
{"1", "root1@msg.id", "root1"},
{"2", "root2@msg.id", "root2"},
/* next one's been promoted 2.0.0 => 2.0 */
@ -169,8 +169,8 @@ test_mu_threads_01 (void)
{"3", "child3.0.0.0.0@msg.id", "Re: child 3.0.0.0"},
/* two children of absent root 4.0 */
{"4:0", "child4.0@msg.id", "Re: child 4.0"},
{"4:1", "child4.1@msg.id", "Re: child 4.1"}
{"4:0", "child4.1@msg.id", "Re: child 4.1"},
{"4:1", "child4.0@msg.id", "Re: child 4.0"}
};
xpath = fill_database (MU_TESTMAILDIR3);
@ -308,13 +308,13 @@ test_mu_threads_sort_2nd_child_promotes_thread (void)
{ "0", "A@msg.id", "A"},
{ "1", "D@msg.id", "D"},
{ "2", "B@msg.id", "B"},
{ "2:0", "C@msg.id", "C"},
{ "2:1", "E@msg.id", "E"},
{ "2:0", "E@msg.id", "E"},
{ "2:1", "C@msg.id", "C"},
};
const tinfo expected_desc [] = {
{ "0", "B@msg.id", "B"},
{ "0:0", "E@msg.id", "E"},
{ "0:1", "C@msg.id", "C"},
{ "0:0", "C@msg.id", "C"},
{ "0:1", "E@msg.id", "E"},
{ "1", "D@msg.id", "D"},
{ "2", "A@msg.id", "A"},
};
@ -334,12 +334,12 @@ test_mu_threads_sort_orphan_promotes_thread (void)
const tinfo expected_asc [] = {
{ "0", "A@msg.id", "A"},
{ "1", "D@msg.id", "D"},
{ "2:0", "C@msg.id", "C"},
{ "2:1", "E@msg.id", "E"},
{ "2:0", "E@msg.id", "E"},
{ "2:1", "C@msg.id", "C"},
};
const tinfo expected_desc [] = {
{ "0:0", "E@msg.id", "E"},
{ "0:1", "C@msg.id", "C"},
{ "0:0", "C@msg.id", "C"},
{ "0:1", "E@msg.id", "E"},
{ "1", "D@msg.id", "D"},
{ "2", "A@msg.id", "A"},
};
@ -357,16 +357,16 @@ test_mu_threads_sort_child_does_not_promote_thread (void)
const char *query = "maildir:/sort/child-does-not-promote-thread";
const tinfo expected_asc [] = {
{ "0", "X@msg.id", "X"},
{ "1", "Y@msg.id", "Y"},
{ "1:0", "A@msg.id", "A"},
{ "0", "Y@msg.id", "Y"},
{ "0:0", "A@msg.id", "A"},
{ "1", "X@msg.id", "X"},
{ "2", "Z@msg.id", "Z"},
};
const tinfo expected_desc [] = {
{ "0", "Z@msg.id", "Z"},
{ "1", "Y@msg.id", "Y"},
{ "1:0", "A@msg.id", "A"},
{ "2", "X@msg.id", "X"},
{ "1", "X@msg.id", "X"},
{ "2", "Y@msg.id", "Y"},
{ "2:0", "A@msg.id", "A"},
};
check_sort_by_subject_asc (query, expected_asc,
@ -409,19 +409,19 @@ test_mu_threads_sort_granchild_promotes_only_subthread (void)
const tinfo expected_asc [] = {
{ "0", "A@msg.id", "A"},
{ "1", "B@msg.id", "B"},
{ "1:0", "C@msg.id", "C"},
{ "1:1", "E@msg.id", "E"},
{ "1:2", "D@msg.id", "D"},
{ "1:2:0", "F@msg.id", "F"},
{ "1:0", "E@msg.id", "E"},
{ "1:1", "D@msg.id", "D"},
{ "1:1:0", "F@msg.id", "F"},
{ "1:2", "C@msg.id", "C"},
{ "2", "G@msg.id", "G"},
};
const tinfo expected_desc [] = {
{ "0", "G@msg.id", "G"},
{ "1", "B@msg.id", "B"},
{ "1:0", "D@msg.id", "D"},
{ "1:0:0", "F@msg.id", "F"},
{ "1:1", "E@msg.id", "E"},
{ "1:2", "C@msg.id", "C"},
{ "1:0", "C@msg.id", "C"},
{ "1:1", "D@msg.id", "D"},
{ "1:1:0", "F@msg.id", "F"},
{ "1:2", "E@msg.id", "E"},
{ "2", "A@msg.id", "A"},
};