summaryrefslogtreecommitdiff
path: root/plugins/HistoryStats/src/column.h
blob: 495c65b5f3b8237890cccdd073e8e6a8b52c88fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
#if !defined(HISTORYSTATS_GUARD_COLUMN_H)
#define HISTORYSTATS_GUARD_COLUMN_H

#include "stdafx.h"
#include "_consts.h"

#include "contact.h"
#include "optionsctrl.h"
#include "settingstree.h"
#include "statistic.h"
#include "message.h"

#include <vector>

/*
 * Column
 */

class Column
	: private pattern::NotCopyable<Column>
{
private:
	class FactoryBase
	{
	public:
		virtual Column* makeInstance() = 0;
	};

	template<typename T_>
	class Factory
		: public FactoryBase
	{
	public:
		virtual Column* makeInstance() { return new T_; }
	};

	class ColumnInfo
	{
	public:
		ext::string m_UID;
		const wchar_t* m_Title;
		const wchar_t* m_Description;
		FactoryBase* m_pFactory;
	};

	class FactoryList
	{
	public:
		std::vector<ColumnInfo> m_List;

	public:
		FactoryList();
		~FactoryList();
		void initList();
	};

public:
	class IDProvider
	{
	private:
		int m_nNextID;

	public:
		IDProvider() : m_nNextID(1) { }
		ext::string getID();
	};

private:
	static FactoryList m_Factories;

public:
	static void registerColumns() { m_Factories.initList(); }
	static Column* fromUID(const ext::string& guid);
	static void registerUID(FactoryBase* pFactory);
	static int countColInfo() { return m_Factories.m_List.size(); }
	static const ColumnInfo& getColInfo(int index) { return m_Factories.m_List[index]; }

	static bool inRange(int nValue, int nMin, int nMax) { return (nValue >= nMin && nValue <= nMax); }

public:
	enum DisplayType {
		asContact,
		asOmitted,
		asTotal,
	};

	enum ColumnFlags {
		cfAcquiresData   = 0x01,
		cfTransformsData = 0x02,
		cfHasConfig      = 0x04,
		// internal, a bit hackish
		cfIsColBaseWords = 0x08,
	};

	enum ConfigRestrictions {
		// supported HTML output modes
		crHTMLPartial = 0x01, // MEMO: never implement columns with only partial HTML support (only full or none)
		crHTMLFull    = 0x03, // includes crHTMPPartial
		crHTMLMask    = 0x0F,
		
		// supported PNG output modes
		crPNGPartial  = 0x10,
		crPNGFull     = 0x30, // includes crPNGPartial
		crPNGMask     = 0xF0,
		
		// valid column restrictions:
		// - crHTMLFull
		// - crHTMLFull | crPNGPartial
		// - crHTMLFull | crPNGFull
		// - crPNGFull
	};

	typedef std::pair<ext::string, ext::string> StylePair;
	typedef std::vector<StylePair> StyleList;

private:
	int m_nContactDataSlot;
	int m_nContactDataTransformSlot;

	bool m_bEnabled;
	ext::string m_CustomTitle;

	Statistic* m_pStatistic;
	Settings* m_pSettings;
	Settings::CharMapper* m_pCharMapper;

	bool m_bUsePNG;

protected:
	/*
	 * Renders a TD with row "row" out of "numRows" having the information
	 * about total rowspan "rowSpan" and colspan "colSpan".
	 */
	void writeRowspanTD(ext::ostream& tos, const ext::string& innerHTML, int row = 1, int numRows = 1, int rowSpan = 1, int colSpan = 1) const;

	void copyAttrib(const Column* pSource);

public:
	Column()
		: m_bEnabled(true), m_CustomTitle(L""),
		m_nContactDataSlot(-1), m_nContactDataTransformSlot(-1),
		m_pStatistic(nullptr), m_pSettings(nullptr), m_pCharMapper(nullptr),
		m_bUsePNG(false)
	{
	}
	virtual ~Column() { }

	void contactDataSlotAssign(int contactDataSlot) { m_nContactDataSlot = contactDataSlot; }
	int contactDataSlotGet() const { return m_nContactDataSlot; }
	void contactDataTransformSlotAssign(int contactDataTransformSlot) { m_nContactDataTransformSlot = contactDataTransformSlot; }
	int contactDataTransformSlotGet() const { return m_nContactDataTransformSlot; }
	
	void setEnabled(bool bEnable) { m_bEnabled = bEnable; }
	bool isEnabled() const { return m_bEnabled; }
	void setCustomTitle(const ext::string& customTitle) { m_CustomTitle = customTitle; }
	const ext::string getCustomTitle() const { return m_CustomTitle; }
	const ext::string getCustomTitle(const ext::string& strShort, const ext::string& strLong) const;
	ext::string getTitleForOptions() { return m_CustomTitle.empty() ? TranslateW(getTitle()) : (m_CustomTitle + L" (" + TranslateW(getTitle()) + L")"); }
	
	void setHelpers(Statistic* pStatistic, Settings* pSettings, Settings::CharMapper* pCharMapper) { m_pStatistic = pStatistic; m_pSettings = pSettings; m_pCharMapper = pCharMapper; }
	Statistic* getStatistic() const { return m_pStatistic; }
	const Settings* getSettings() const { return m_pSettings; }
	const Settings::CharMapper* getCharMapper() const { return m_pCharMapper; }

	bool usePNG() { return m_bUsePNG; }

	Column* clone() const;

public:
	/*
	 * public interface for virtual functions
	 */
	const wchar_t* getUID() const { return impl_getUID(); }
	const wchar_t* getTitle() const { return impl_getTitle(); }
	const wchar_t* getDescription() const { return impl_getDescription(); }
	void copyConfig(const Column* pSource) { impl_copyConfig(pSource); }
	int getFeatures() const { return impl_getFeatures(); }
	void configRead(const SettingsTree& settings) { impl_configRead(settings); }
	void configWrite(SettingsTree& settings) const { impl_configWrite(settings); }
	void configToUI(OptionsCtrl& Opt, OptionsCtrl::Item hGroup) { impl_configToUI(Opt, hGroup); }
	void configFromUI(OptionsCtrl& Opt) { impl_configFromUI(Opt); }
	int configGetRestrictions(ext::string* pDetails) const { return impl_configGetRestrictions(pDetails); }
	ext::string contactDataGetUID() const { return impl_contactDataGetUID(); }
	void contactDataBeginAcquire() { impl_contactDataBeginAcquire(); }
	void contactDataEndAcquire() { impl_contactDataEndAcquire(); }
	void contactDataPrepare(Contact& contact) const { impl_contactDataPrepare(contact); }
	void contactDataFree(Contact& contact) const { impl_contactDataFree(contact); }
	void contactDataAcquireMessage(Contact& contact, Message& msg) { impl_contactDataAcquireMessage(contact, msg); }
	void contactDataAcquireChat(Contact& contact, bool bOutgoing, uint32_t localTimestampStarted, uint32_t duration) { impl_contactDataAcquireChat(contact, bOutgoing, localTimestampStarted, duration); }
	void contactDataMerge(Contact& contact, const Contact& include) const { impl_contactDataMerge(contact, include); }
	void contactDataTransform(Contact& contact) const { impl_contactDataTransform(contact); }
	void contactDataTransformCleanup(Contact& contact) const { impl_contactDataTransformCleanup(contact); }
	void columnDataBeforeOmit() { impl_columnDataBeforeOmit(); }
	void columnDataAfterOmit() { impl_columnDataAfterOmit(); }
	StyleList outputGetAdditionalStyles(IDProvider& idp) { return impl_outputGetAdditionalStyles(idp); }
	SIZE outputMeasureHeader() const { return impl_outputMeasureHeader(); }
	void outputRenderHeader(ext::ostream& tos, int row, int rowSpan) const { impl_outputRenderHeader(tos, row, rowSpan); }
	void outputBegin();
	void outputEnd() { impl_outputEnd(); }
	void outputRenderRow(ext::ostream& tos, const Contact& contact, DisplayType display) { impl_outputRenderRow(tos, contact, display); }

protected:
	/*** VIRTUAL/ABSTRACT *** GLOBAL ***/

	/*
	 * Returns a unique ID for column.
	 * [virtual/abstract]
	 */
	virtual const wchar_t* impl_getUID() const = 0;

	/*
	 * Returns the title for the column.
	 * [virtual/abstract]
	 */
	virtual const wchar_t* impl_getTitle() const = 0;

	/*
	 * Returns the description for the column.
	 * [virtual/abstract]
	 */
	virtual const wchar_t* impl_getDescription() const = 0;

	/*
	 * Creates a exact copy of the column.
	 * [virtual/default: copy nothing]
	 */
	virtual void impl_copyConfig(const Column*) { }

	/*
	 * Queries for column's features.
	 * [virtual/abstract]
	 */
	virtual int impl_getFeatures() const = 0;

	/*** VIRTUAL/ABSTRACT *** CONFIGURATION ***/

	/*
	 * [virtual/default: do nothing]
	 */
	virtual void impl_configRead(const SettingsTree&) { }

	/*
	 * [vurtual/default: do nothing]
	 */
	virtual void impl_configWrite(SettingsTree&) const { }

	/*
	 * [virtual/default: do nothing]
	 */
	virtual void impl_configToUI(OptionsCtrl&, OptionsCtrl::Item) { }

	/*
	 * [virtual/default: do nothing]
	 */
	virtual void impl_configFromUI(OptionsCtrl&) { }

	/*
	 * Check if current column options imply output restrictions.
	 * [virtual/abstract]
	 */
	virtual int impl_configGetRestrictions(ext::string* pDetails) const = 0;

	/*** VIRTUAL/ABSTRACT *** PER-CONTACT DATA ACQUISITION ***/

	/*
	 * Returns a unique ID for the type of additional per-contact
	 * data collected by this column (for sharing data between columns).
	 * Ignores, if column doesn't acquire any data.
	 * [virtual/default: empty string]
	 */
	virtual ext::string impl_contactDataGetUID() const { return ext::string(); }

	/*
	 * Perform initialization of column-global data before acquisition.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataBeginAcquire() { }

	/*
	 * Perform finalization of column-global data after acuqisition.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataEndAcquire() { }

	/*
	 * Initializes data structures for acquiring additional per-contact
	 * data for given contact. Works on previously defined slot.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataPrepare(Contact&) const { }

	/*
	 * Frees all data structures associated with this column for the
	 * given contact. Works on previously defined slot.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataFree(Contact&) const { }

	/*
	 * Acquires data for this column and for the given contact. Works
	 * on previously defined slot.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataAcquireMessage(Contact&, Message&) { }

	/*
	 * Acquires data for this column and for the given contact. Works
	 * on previously defined slot.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataAcquireChat(Contact&, bool, uint32_t, uint32_t) { }

	/*** VIRTUAL/ABSTRACT *** DATA POSTPROCESSING ***/

	/*
	 * Merges additonal per-contact data for two contacts. Not called, if
	 * column doesn't acquire any data.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataMerge(Contact&, const Contact&) const { }

	/*
	 * Perform any post processing for additional per-contact data. Will
	 * be called after merge but before sort.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataTransform(Contact&) const { }

	/*
	 * Perform cleanup after post processing.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_contactDataTransformCleanup(Contact&) const { }

	/*** VIRTUAL/ABSTRACT *** COLUMN SPECIFIC GLOBAL DATA ***/

	/*
	 * [virtual/default: do nothing]
	 */
	virtual void impl_columnDataBeforeOmit() { }

	/*
	 * [virtual/default: do nothing]
	 */
	virtual void impl_columnDataAfterOmit() { }

	/*** VIRTUAL/ABSTRACT *** OUTPUT ***/

	/*
	 * Returns additional (i.e. non-default) styles required by this
	 * column as a list of CSS selectors (first) and CSS styles (second).
	 * [virtual/default: empty list]
	 */
	virtual StyleList impl_outputGetAdditionalStyles(IDProvider&) { return StyleList(); }

	/*
	 * Returns number of columns and table rows (for header only) used by
	 * this column.
	 * [virtual/default: 1 row and 1 column]
	 */
	virtual SIZE impl_outputMeasureHeader() const;

	/*
	 * Renders the row "row" of the header to the output stream "tos". The
	 * parameter "rowSpan" specifies the previously calculated number of
	 * total header rowspan.
	 * [virtual/abstract]
	 */
	virtual void impl_outputRenderHeader(ext::ostream& tos, int row, int rowSpan) const = 0;

	/*
	 * Perform column-global initialization before output.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_outputBegin() { }

	/*
	 * Perform column-global finalization before output.
	 * [virtual/default: do nothing]
	 */
	virtual void impl_outputEnd() { }

	/*
	 * Renders the given contact "contact" to the output stream "tos" and
	 * modfies rendering depending on value in "display".
	 * [virtual/abstract]
	 */
	virtual void impl_outputRenderRow(ext::ostream& tos, const Contact& contact, DisplayType display) = 0;
};

#endif // HISTORYSTATS_GUARD_COLUMN_H