summaryrefslogtreecommitdiff
path: root/lsscenemodel.cpp
blob: f5c4ba3cf749860adf1bb321b59900523ce6bbc8 (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
#include "lsscenemodel.h"
#include "lsglobals.h"

LSSceneModel::LSSceneModel(LYTLayout *layout, QObject *parent) :
	QAbstractItemModel(parent)
{
	m_layout = layout;

	m_paneIcons[LYTPane::PaneType] = LSGlobals::getIcon("pane");
	m_paneIcons[LYTPane::PictureType] = LSGlobals::getIcon("picture");
	m_paneIcons[LYTPane::TextBoxType] = LSGlobals::getIcon("textbox");
	m_paneIcons[LYTPane::WindowType] = LSGlobals::getIcon("window");
	m_paneIcons[LYTPane::BoundingType] = LSGlobals::getIcon("bounding");

	m_movingPaneParent = 0;
}

LSSceneModel::~LSSceneModel() {
	if (m_movingPaneParent)
		delete m_movingPaneParent;
}


QModelIndex LSSceneModel::index(int row, int column, const QModelIndex &parent) const {
	if (!hasIndex(row, column, parent))
		return QModelIndex();

	if (!parent.isValid())
		return createIndex(row, column, m_layout->rootPane);

	// what's the parent..?
	LYTPane *parentPane = (LYTPane*)parent.internalPointer();
	LYTPane *pane = parentPane->children.at(row);
	return createIndex(row, column, pane);
}

QModelIndex LSSceneModel::parent(const QModelIndex &child) const {
	if (!child.isValid())
		return QModelIndex();

	LYTPane *childPane = (LYTPane*)child.internalPointer();
	LYTPane *parentPane = childPane->parent;
	if (parentPane) {
		LYTPane *parentParentPane = parentPane->parent;
		int index = parentParentPane ? parentParentPane->children.indexOf(parentPane) : 0;
		return createIndex(index, 0, parentPane);
	} else {
		return QModelIndex();
	}
}

int LSSceneModel::rowCount(const QModelIndex &parent) const {
	if (!parent.isValid()) {
		return 1; // the root pane
	}

	LYTPane *parentPane = (LYTPane*)parent.internalPointer();
	return parentPane->children.count();
}

int LSSceneModel::columnCount(const QModelIndex &parent) const {
	(void)parent;
	return 1;
}

QVariant LSSceneModel::data(const QModelIndex &index, int role) const {
	LYTPane *pane = (LYTPane*)index.internalPointer();
	if (pane) {
		switch (role) {
		case Qt::DisplayRole:
			return pane->name;
		case Qt::DecorationRole:
			return m_paneIcons[pane->type()];
		}
	}
	return QVariant();
}


Qt::ItemFlags LSSceneModel::flags(const QModelIndex &index) const {
	Qt::ItemFlags flag;
	flag = Qt::ItemIsEnabled | Qt::ItemIsSelectable |
			Qt::ItemIsDropEnabled | Qt::ItemIsEditable;

	if (index.isValid() && index.parent().isValid())
		flag |= Qt::ItemIsDragEnabled;

	return flag;
}


Qt::DropActions LSSceneModel::supportedDropActions() const {
	return Qt::MoveAction;
}


// I am doing a terrible, terrible, terrible thing here.
// I hate drag-and-drop.

// As far as I can see, insertRows and removeRows are ONLY called by Qt when
// dragging something. So instead of doing a real insertion/removal... I'll
// store the intended destination, and once I'm told what pane needs to be
// removed (moved) I do the whole thing at once.

bool LSSceneModel::insertRows(int row, int count, const QModelIndex &parent) {
	qDebug("LSSceneModel::insertRows(%d, %d, something)", row, count);

	if (m_movingPaneParent) {
		qWarning("huh, already moving something? dunno");
		return false;
	}

	m_movingPaneParent = new QPersistentModelIndex(parent);
	m_movingPaneRow = row;
	m_movingPaneCount = count;

	return true;
}

bool LSSceneModel::removeRows(int row, int count, const QModelIndex &parent) {
	qDebug("LSSceneModel::removeRows(%d, %d, something)", row, count);

	if (!m_movingPaneParent) {
		qWarning("huh, not moving anything / nothing left to move? dunno");
		return false;
	}

	// detach all the existing panes
	LYTPane *parentPane = (LYTPane*)parent.internalPointer();

	QVector<LYTPane *> removingPanes;
	removingPanes.reserve(count);

	beginRemoveRows(parent, row, row + count - 1);
	for (int i = 0; i < count; i++) {
		removingPanes.append(parentPane->children.at(row));
		parentPane->children.removeAt(row);
	}
	endRemoveRows();

	// now add them in their new homes!
	LYTPane *newParentPane = (LYTPane*)m_movingPaneParent->internalPointer();

	// note: compensate for the offset: if we're moving the thing within the
	// same parent and the destination row is higher than the source row, then
	// removing the source row will have changed the index of the row the user
	// actually wanted to move the moved row to... what a terrible sentence :|
	if (*m_movingPaneParent == parent && m_movingPaneRow > row)
		m_movingPaneRow -= count;

	beginInsertRows(*m_movingPaneParent, m_movingPaneRow, m_movingPaneRow + count - 1);

	for (int i = 0; i < count; i++) {
		LYTPane *pane = removingPanes.at(i);

		pane->parent = newParentPane;
		newParentPane->children.insert(m_movingPaneRow, pane);

		m_movingPaneRow++;
	}

	endInsertRows();

	// clean up if needed
	m_movingPaneCount -= count;

	if (m_movingPaneCount <= 0) {
		delete m_movingPaneParent;
		m_movingPaneParent = 0;
	}

	return true;
}