File indexing completed on 2025-02-16 04:59:36
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org> 0003 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 0007 0008 #ifndef DOMAIN_QUERYRESULTPROVIDER_H 0009 #define DOMAIN_QUERYRESULTPROVIDER_H 0010 0011 #include <algorithm> 0012 #include <functional> 0013 0014 #include <QList> 0015 #include <QSharedPointer> 0016 0017 #include "utils/mem_fn.h" 0018 0019 namespace Domain { 0020 0021 template<typename ItemType> 0022 class QueryResultProvider; 0023 0024 template<typename InputType> 0025 class QueryResultInputImpl 0026 { 0027 public: 0028 typedef typename QueryResultProvider<InputType>::Ptr ProviderPtr; 0029 typedef QSharedPointer<QueryResultInputImpl<InputType> > Ptr; 0030 typedef QWeakPointer<QueryResultInputImpl<InputType>> WeakPtr; 0031 typedef std::function<void(InputType, int)> ChangeHandler; 0032 typedef QList<ChangeHandler> ChangeHandlerList; 0033 0034 virtual ~QueryResultInputImpl() {} 0035 0036 protected: 0037 explicit QueryResultInputImpl(const ProviderPtr &provider) 0038 : m_provider(provider) 0039 { 0040 } 0041 0042 static void registerResult(const ProviderPtr &provider, const Ptr &result) 0043 { 0044 provider->m_results << result; 0045 } 0046 0047 static ProviderPtr retrieveProvider(const Ptr &result) 0048 { 0049 return result->m_provider; 0050 } 0051 0052 // cppcheck can't figure out the friend class 0053 // cppcheck-suppress unusedPrivateFunction 0054 ChangeHandlerList preInsertHandlers() const 0055 { 0056 return m_preInsertHandlers; 0057 } 0058 0059 // cppcheck can't figure out the friend class 0060 // cppcheck-suppress unusedPrivateFunction 0061 ChangeHandlerList postInsertHandlers() const 0062 { 0063 return m_postInsertHandlers; 0064 } 0065 0066 // cppcheck can't figure out the friend class 0067 // cppcheck-suppress unusedPrivateFunction 0068 ChangeHandlerList preRemoveHandlers() const 0069 { 0070 return m_preRemoveHandlers; 0071 } 0072 0073 // cppcheck can't figure out the friend class 0074 // cppcheck-suppress unusedPrivateFunction 0075 ChangeHandlerList postRemoveHandlers() const 0076 { 0077 return m_postRemoveHandlers; 0078 } 0079 0080 // cppcheck can't figure out the friend class 0081 // cppcheck-suppress unusedPrivateFunction 0082 ChangeHandlerList preReplaceHandlers() const 0083 { 0084 return m_preReplaceHandlers; 0085 } 0086 0087 // cppcheck can't figure out the friend class 0088 // cppcheck-suppress unusedPrivateFunction 0089 ChangeHandlerList postReplaceHandlers() const 0090 { 0091 return m_postReplaceHandlers; 0092 } 0093 0094 friend class QueryResultProvider<InputType>; 0095 ProviderPtr m_provider; 0096 ChangeHandlerList m_preInsertHandlers; 0097 ChangeHandlerList m_postInsertHandlers; 0098 ChangeHandlerList m_preRemoveHandlers; 0099 ChangeHandlerList m_postRemoveHandlers; 0100 ChangeHandlerList m_preReplaceHandlers; 0101 ChangeHandlerList m_postReplaceHandlers; 0102 }; 0103 0104 template<typename ItemType> 0105 class QueryResultProvider 0106 { 0107 public: 0108 typedef QSharedPointer<QueryResultProvider<ItemType>> Ptr; 0109 typedef QWeakPointer<QueryResultProvider<ItemType>> WeakPtr; 0110 0111 typedef QSharedPointer<QueryResultInputImpl<ItemType> > ResultPtr; 0112 typedef QWeakPointer<QueryResultInputImpl<ItemType>> ResultWeakPtr; 0113 typedef std::function<void(ItemType, int)> ChangeHandler; 0114 typedef QList<ChangeHandler> ChangeHandlerList; 0115 0116 0117 QueryResultProvider() 0118 { 0119 } 0120 0121 QList<ItemType> data() const 0122 { 0123 return m_list; 0124 } 0125 0126 void append(const ItemType &item) 0127 { 0128 cleanupResults(); 0129 callChangeHandlers(item, m_list.size(), 0130 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preInsertHandlers)); 0131 m_list.append(item); 0132 callChangeHandlers(item, m_list.size()-1, 0133 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postInsertHandlers)); 0134 } 0135 0136 void prepend(const ItemType &item) 0137 { 0138 cleanupResults(); 0139 callChangeHandlers(item, 0, 0140 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preInsertHandlers)); 0141 m_list.prepend(item); 0142 callChangeHandlers(item, 0, 0143 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postInsertHandlers)); 0144 } 0145 0146 void insert(int index, const ItemType &item) 0147 { 0148 cleanupResults(); 0149 callChangeHandlers(item, index, 0150 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preInsertHandlers)); 0151 m_list.insert(index, item); 0152 callChangeHandlers(item, index, 0153 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postInsertHandlers)); 0154 } 0155 0156 ItemType takeFirst() 0157 { 0158 cleanupResults(); 0159 const ItemType item = m_list.first(); 0160 callChangeHandlers(item, 0, 0161 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preRemoveHandlers)); 0162 m_list.removeFirst(); 0163 callChangeHandlers(item, 0, 0164 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postRemoveHandlers)); 0165 return item; 0166 } 0167 0168 void removeFirst() 0169 { 0170 takeFirst(); 0171 } 0172 0173 ItemType takeLast() 0174 { 0175 cleanupResults(); 0176 const ItemType item = m_list.last(); 0177 callChangeHandlers(item, m_list.size()-1, 0178 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preRemoveHandlers)); 0179 m_list.removeLast(); 0180 callChangeHandlers(item, m_list.size(), 0181 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postRemoveHandlers)); 0182 return item; 0183 } 0184 0185 void removeLast() 0186 { 0187 takeLast(); 0188 } 0189 0190 ItemType takeAt(int index) 0191 { 0192 cleanupResults(); 0193 const ItemType item = m_list.at(index); 0194 callChangeHandlers(item, index, 0195 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preRemoveHandlers)); 0196 m_list.removeAt(index); 0197 callChangeHandlers(item, index, 0198 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postRemoveHandlers)); 0199 return item; 0200 } 0201 0202 void removeAt(int index) 0203 { 0204 takeAt(index); 0205 } 0206 0207 void replace(int index, const ItemType &item) 0208 { 0209 cleanupResults(); 0210 callChangeHandlers(m_list.at(index), index, 0211 Utils::mem_fn(&QueryResultInputImpl<ItemType>::preReplaceHandlers)); 0212 m_list.replace(index, item); 0213 callChangeHandlers(item, index, 0214 Utils::mem_fn(&QueryResultInputImpl<ItemType>::postReplaceHandlers)); 0215 } 0216 0217 QueryResultProvider &operator<< (const ItemType &item) 0218 { 0219 append(item); 0220 return *this; 0221 } 0222 0223 private: 0224 void cleanupResults() 0225 { 0226 m_results.erase(std::remove_if(m_results.begin(), 0227 m_results.end(), 0228 Utils::mem_fn(&QueryResultInputImpl<ItemType>::WeakPtr::isNull)), 0229 m_results.end()); 0230 } 0231 0232 typedef std::function<ChangeHandlerList(ResultPtr)> ChangeHandlerGetter; 0233 0234 void callChangeHandlers(const ItemType &item, int index, const ChangeHandlerGetter &handlerGetter) 0235 { 0236 for (auto weakResult : m_results) 0237 { 0238 auto result = weakResult.toStrongRef(); 0239 if (!result) continue; 0240 for (auto handler : handlerGetter(result)) 0241 { 0242 handler(item, index); 0243 } 0244 } 0245 } 0246 0247 friend class QueryResultInputImpl<ItemType>; 0248 QList<ItemType> m_list; 0249 QList<ResultWeakPtr> m_results; 0250 }; 0251 0252 } 0253 0254 #endif // DOMAIN_QUERYRESULTPROVIDER_H