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
|
#ifndef MODLISTVIEW_H
#define MODLISTVIEW_H
#include <map>
#include <set>
#include <vector>
#include <QDragEnterEvent>
#include <QLCDNumber>
#include <QLabel>
#include <QTreeView>
#include "modlistsortproxy.h"
#include "qtgroupingproxy.h"
#include "viewmarkingscrollbar.h"
namespace Ui
{
class MainWindow;
}
class CategoryFactory;
class FilterList;
class OrganizerCore;
class MainWindow;
class Profile;
class ModListByPriorityProxy;
class ModListViewActions;
class PluginListView;
class ModListView : public QTreeView
{
Q_OBJECT
public:
// this is a public version of DropIndicatorPosition
enum DropPosition
{
OnItem = DropIndicatorPosition::OnItem,
AboveItem = DropIndicatorPosition::AboveItem,
BelowItem = DropIndicatorPosition::BelowItem,
OnViewport = DropIndicatorPosition::OnViewport
};
// indiucate the groupby mode
enum class GroupByMode
{
NONE,
SEPARATOR,
CATEGORY,
NEXUS_ID
};
public:
explicit ModListView(QWidget* parent = 0);
void setup(OrganizerCore& core, CategoryFactory& factory, MainWindow* mw,
Ui::MainWindow* mwui);
// restore/save the state between session
//
void restoreState(const Settings& s);
void saveState(Settings& s) const;
// check if collapsible separators are currently used
//
bool hasCollapsibleSeparators() const;
// the column/order by which the mod list is currently sorted
//
int sortColumn() const;
Qt::SortOrder sortOrder() const;
// check if a filter is currently active
//
bool isFilterActive() const;
// the current group mode
//
GroupByMode groupByMode() const;
// retrieve the actions from the view
//
ModListViewActions& actions() const;
// retrieve the next/previous mod in the current view, the given index
// should be a mod index (not a model row)
//
std::optional<unsigned int> nextMod(unsigned int index) const;
std::optional<unsigned int> prevMod(unsigned int index) const;
// check if the given mod is visible, i.e. not filtered (returns true
// for collapsed mods)
//
bool isModVisible(unsigned int index) const;
bool isModVisible(ModInfo::Ptr mod) const;
// focus the view, select the given index and scroll to it
//
void scrollToAndSelect(const QModelIndex& index);
void scrollToAndSelect(const QModelIndexList& indexes,
const QModelIndex& current = QModelIndex());
// refresh the view (to call when settings have been changed)
//
void refresh();
signals:
// emitted for dragEnter events
//
void dragEntered(const QMimeData* mimeData);
// emitted for dropEnter events, the boolean indicates if the drop target
// is expanded and the position of the indicator
//
void dropEntered(const QMimeData* mimeData, bool dropExpanded, DropPosition position);
public slots:
// invalidate (refresh) the filter (similar to a layout changed event)
//
void invalidateFilter();
// set the filter criteria/options for mods
//
void setFilterCriteria(const std::vector<ModListSortProxy::Criteria>& criteria);
void setFilterOptions(ModListSortProxy::FilterMode mode,
ModListSortProxy::SeparatorsMode sep);
// update the mod counter
//
void updateModCount();
// refresh the filters
//
void refreshFilters();
// set highligth markers
//
void setHighlightedMods(const std::set<QString>& modNames);
protected:
// map from/to the view indexes to the model
//
QModelIndex indexModelToView(const QModelIndex& index) const;
QModelIndexList indexModelToView(const QModelIndexList& index) const;
QModelIndex indexViewToModel(const QModelIndex& index) const;
QModelIndexList indexViewToModel(const QModelIndexList& index) const;
// returns the next/previous index of the given index
//
QModelIndex nextIndex(const QModelIndex& index) const;
QModelIndex prevIndex(const QModelIndex& index) const;
// re-implemented to fake the return value to allow drag-and-drop on
// itself for separators
//
QModelIndexList selectedIndexes() const;
// drop from external folder
//
void onExternalFolderDropped(const QUrl& url, int priority);
// method to react to various key events
//
bool moveSelection(int key);
bool removeSelection();
bool toggleSelectionState();
// re-implemented to fix indentation with collapsible separators
//
QRect visualRect(const QModelIndex& index) const override;
void drawBranches(QPainter* painter, const QRect& rect,
const QModelIndex& index) const override;
void timerEvent(QTimerEvent* event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
void dropEvent(QDropEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
bool event(QEvent* event) override;
protected slots:
void onCustomContextMenuRequested(const QPoint& pos);
void onDoubleClicked(const QModelIndex& index);
void onFiltersCriteria(const std::vector<ModListSortProxy::Criteria>& filters);
void onProfileChanged(Profile* oldProfile, Profile* newProfile);
void commitData(QWidget* editor) override;
private: // friend classes
friend class ModConflictIconDelegate;
friend class ModContentIconDelegate;
friend class ModFlagIconDelegate;
friend class ModListContextMenu;
friend class ModListStyledItemDelegate;
friend class ModListViewActions;
friend class ModListViewMarkingScrollBar;
private: // private structures
struct ModListViewUi
{
// the group by combo box
QComboBox* groupBy;
// the mod counter
QLCDNumber* counter;
// filters related
QLineEdit* filter;
QLabel* currentCategory;
QPushButton* clearFilters;
QComboBox* filterSeparators;
// the plugin list (for highlights)
PluginListView* pluginList;
};
struct MarkerInfos
{
// conflicts
std::set<unsigned int> overwrite;
std::set<unsigned int> overwritten;
std::set<unsigned int> archiveOverwrite;
std::set<unsigned int> archiveOverwritten;
std::set<unsigned int> archiveLooseOverwrite;
std::set<unsigned int> archiveLooseOverwritten;
// selected plugins
std::set<unsigned int> highlight;
};
struct ModCounters
{
int active = 0;
int backup = 0;
int foreign = 0;
int separator = 0;
int regular = 0;
struct
{
int active = 0;
int backup = 0;
int foreign = 0;
int separator = 0;
int regular = 0;
} visible;
};
// index in the groupby combo
//
enum GroupBy
{
NONE = 0,
CATEGORY = 1,
NEXUS_ID = 2
};
private: // private functions
void onModPrioritiesChanged(const QModelIndexList& indices);
void onModInstalled(const QString& modName);
void onModFilterActive(bool filterActive);
// refresh the overwrite markers and the highlighted plugins from
// the current selection
//
void refreshMarkersAndPlugins();
// clear overwrite markers (without repainting)
//
void clearOverwriteMarkers();
// set overwrite markers from the mod in the given list and repaint (if the list
// is empty, clear overwrite and repaint)
//
void setOverwriteMarkers(const QModelIndexList& indexes);
// retrieve the marker color for the given index
//
QColor markerColor(const QModelIndex& index) const;
// retrieve the mod flags for the given index
//
std::vector<ModInfo::EFlag> modFlags(const QModelIndex& index,
bool* forceCompact = nullptr) const;
// retrieve the conflicts flags for the given index
//
std::vector<ModInfo::EConflictFlag> conflictFlags(const QModelIndex& index,
bool* forceCompact = nullptr) const;
// retrieve the content icons and tooltip for the given index
//
std::set<int> contents(const QModelIndex& index, bool* includeChildren) const;
QList<QString> contentsIcons(const QModelIndex& index,
bool* forceCompact = nullptr) const;
QString contentsTooltip(const QModelIndex& index) const;
// compute the counters for mods according to the current filter
//
ModCounters counters() const;
// get/set the selected items on the view, this method return/take indices
// from the mod list model, not the view, so it's safe to restore
//
std::pair<QModelIndex, QModelIndexList> selected() const;
void setSelected(const QModelIndex& current, const QModelIndexList& selected);
// refresh stored expanded items for the current intermediate proxy
//
void refreshExpandedItems();
// refresh the group-by proxy, if the index is -1 will refresh the
// current one (e.g. when changing the sort column)
//
void updateGroupByProxy();
public: // member variables
OrganizerCore* m_core;
std::unique_ptr<FilterList> m_filters;
CategoryFactory* m_categories;
ModListViewUi ui;
ModListViewActions* m_actions;
ModListSortProxy* m_sortProxy;
ModListByPriorityProxy* m_byPriorityProxy;
QtGroupingProxy* m_byCategoryProxy;
QtGroupingProxy* m_byNexusIdProxy;
// marker used to avoid calling refreshing markers to many
// time in a row
QTimer m_refreshMarkersTimer;
// maintain collapsed items for each proxy to avoid
// losing them on model reset
std::map<QAbstractItemModel*, std::set<QString>> m_collapsed;
MarkerInfos m_markers;
ViewMarkingScrollBar* m_scrollbar;
bool m_inDragMoveEvent = false;
// replace the auto-expand timer from QTreeView to avoid
// auto-collapsing
QBasicTimer m_openTimer;
};
#endif // MODLISTVIEW_H
|