Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <LibGUI/Model.h>
10
11namespace GUI {
12
13class SortingProxyModel
14 : public Model
15 , private ModelClient {
16public:
17 static ErrorOr<NonnullRefPtr<SortingProxyModel>> create(NonnullRefPtr<Model> source)
18 {
19 return adopt_nonnull_ref_or_enomem(new (nothrow) SortingProxyModel(move(source)));
20 }
21
22 virtual ~SortingProxyModel() override;
23
24 virtual int tree_column() const override { return m_source->tree_column(); }
25 virtual int row_count(ModelIndex const& = ModelIndex()) const override;
26 virtual int column_count(ModelIndex const& = ModelIndex()) const override;
27 virtual DeprecatedString column_name(int) const override;
28 virtual Variant data(ModelIndex const&, ModelRole = ModelRole::Display) const override;
29 virtual void invalidate() override;
30 virtual StringView drag_data_type() const override;
31 virtual ModelIndex parent_index(ModelIndex const&) const override;
32 virtual ModelIndex index(int row, int column, ModelIndex const& parent) const override;
33 virtual bool is_editable(ModelIndex const&) const override;
34 virtual bool is_searchable() const override;
35 virtual void set_data(ModelIndex const&, Variant const&) override;
36 virtual Vector<ModelIndex> matches(StringView, unsigned = MatchesFlag::AllMatching, ModelIndex const& = ModelIndex()) override;
37 virtual bool accepts_drag(ModelIndex const&, Vector<DeprecatedString> const& mime_types) const override;
38
39 virtual bool is_column_sortable(int column_index) const override;
40
41 virtual bool less_than(ModelIndex const&, ModelIndex const&) const;
42
43 ModelIndex map_to_source(ModelIndex const&) const;
44 ModelIndex map_to_proxy(ModelIndex const&) const;
45
46 ModelRole sort_role() const { return m_sort_role; }
47 void set_sort_role(ModelRole role) { m_sort_role = role; }
48
49 virtual void sort(int column, SortOrder) override;
50
51private:
52 explicit SortingProxyModel(NonnullRefPtr<Model> source);
53
54 // NOTE: The internal_data() of indices points to the corresponding Mapping object for that index.
55 struct Mapping {
56 Vector<int> source_rows;
57 Vector<int> proxy_rows;
58 ModelIndex source_parent;
59 };
60
61 using InternalMapIterator = HashMap<ModelIndex, NonnullOwnPtr<Mapping>>::IteratorType;
62
63 void sort_mapping(Mapping&, int column, SortOrder);
64
65 // ^ModelClient
66 virtual void model_did_update(unsigned) override;
67
68 Model& source() { return *m_source; }
69 Model const& source() const { return *m_source; }
70
71 void update_sort(unsigned = UpdateFlag::DontInvalidateIndices);
72 InternalMapIterator build_mapping(ModelIndex const& proxy_index);
73
74 NonnullRefPtr<Model> m_source;
75
76 HashMap<ModelIndex, NonnullOwnPtr<Mapping>> m_mappings;
77 ModelRole m_sort_role { ModelRole::Sort };
78 int m_last_key_column { -1 };
79 SortOrder m_last_sort_order { SortOrder::Ascending };
80};
81
82}