blob: cb541461803463339e345a90c3419d67fee39341 [file] [log] [blame]
Alexandre Lision8521baa2015-03-13 11:08:00 -04001/*
Alexandre Lision9fe374b2016-01-06 10:17:31 -05002 * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
Alexandre Lision8521baa2015-03-13 11:08:00 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Alexandre Lision8521baa2015-03-13 11:08:00 -040018 */
Alexandre Lision5855b6a2015-02-03 11:31:05 -050019#import "QNSTreeController.h"
Alexandre Lision5855b6a2015-02-03 11:31:05 -050020
Alexandre Lision2db8f472015-07-22 15:05:46 -040021#import <QDebug>
22
Alexandre Lision5855b6a2015-02-03 11:31:05 -050023@interface Node : NSObject {
24 NSMutableArray *children;
25}
26@end
27
28@implementation Node
29- (id) init
30{
31 if (self = [super init]) {
32 children = [[NSMutableArray alloc] init];
33 }
34 return self;
35}
36
Alexandre Lision2db8f472015-07-22 15:05:46 -040037- (void) addChild:(Node*) child AtIndex:(NSUInteger) idx
Alexandre Lision5855b6a2015-02-03 11:31:05 -050038{
Alexandre Lision2db8f472015-07-22 15:05:46 -040039 [children insertObject:child atIndex:idx];
40}
41
42- (NSMutableArray*) children
43{
44 return children;
Alexandre Lision5855b6a2015-02-03 11:31:05 -050045}
46
Alexandre Lision5855b6a2015-02-03 11:31:05 -050047@end
48
49
50@implementation QNSTreeController
51
52- (id) initWithQModel:(QAbstractItemModel*) model
53{
Alexandre Lision81c97212015-06-17 15:51:53 -040054 self = [super init];
Alexandre Lision5855b6a2015-02-03 11:31:05 -050055 self->privateQModel = model;
56
Alexandre Lision2db8f472015-07-22 15:05:46 -040057 NSMutableArray* nodes = [[NSMutableArray alloc] init];
Alexandre Lision2db8f472015-07-22 15:05:46 -040058 [self populate:nodes];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040059
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040060 [self connect];
Alexandre Lision2db8f472015-07-22 15:05:46 -040061 return [self initWithContent:nodes];
Alexandre Lision5855b6a2015-02-03 11:31:05 -050062}
63
Alexandre Lision2db8f472015-07-22 15:05:46 -040064-(void) populate:(NSMutableArray*) nodes
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040065{
Alexandre Lision2db8f472015-07-22 15:05:46 -040066 for (int i = 0 ; i < self->privateQModel->rowCount() ; ++i) {
67 Node* n = [[Node alloc] init];
68 //qDebug() << "POUPL TOP:"<< self->privateQModel->index(i, 0) ;
69 [self populateChild:[n children] withParent:self->privateQModel->index(i, 0)];
70 [nodes insertObject:n atIndex:i];
71 }
72}
73
74- (void) populateChild:(NSMutableArray*) nodes withParent:(QModelIndex)qIdx
75{
76 if (!qIdx.isValid())
77 return;
78 for (int i = 0 ; i < self->privateQModel->rowCount(qIdx) ; ++i) {
79 Node* n = [[Node alloc] init];
Alexandre Lision2db8f472015-07-22 15:05:46 -040080 [self populateChild:[n children] withParent:self->privateQModel->index(i, 0, qIdx)];
81 [nodes insertObject:n atIndex:i];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040082 }
83}
84
Alexandre Lision5855b6a2015-02-03 11:31:05 -050085- (BOOL)isEditable
86{
87 return self->privateQModel->flags(self->privateQModel->index(0, 0)) | Qt::ItemIsEditable;
88}
89
Alexandre Lision2db8f472015-07-22 15:05:46 -040090- (QModelIndex) indexPathtoQIdx:(NSIndexPath*) path
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040091{
Alexandre Lision2db8f472015-07-22 15:05:46 -040092 NSUInteger myArray[[path length]];
93 [path getIndexes:myArray];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040094 QModelIndex toReturn;
Alexandre Lision3b0bd332015-03-15 18:43:07 -040095
Alexandre Lision2db8f472015-07-22 15:05:46 -040096 for (int i = 0; i < path.length; ++i) {
Alexandre Lision3b0bd332015-03-15 18:43:07 -040097 toReturn = self->privateQModel->index(myArray[i], 0, toReturn);
98 }
99
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400100 return toReturn;
101}
102
Alexandre Lision2db8f472015-07-22 15:05:46 -0400103- (QModelIndex) toQIdx:(NSTreeNode*) node
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400104{
Alexandre Lision2db8f472015-07-22 15:05:46 -0400105 return [self indexPathtoQIdx:node.indexPath];
106}
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400107
Alexandre Lision2db8f472015-07-22 15:05:46 -0400108- (NSIndexPath*) qIdxToNSIndexPath:(QModelIndex) qIdx
109{
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400110 QModelIndex tmp = qIdx.parent();
111 NSMutableArray* allIndexes = [NSMutableArray array];
112 while (tmp.isValid()) {
113 [allIndexes insertObject:@(tmp.row()) atIndex:0];
114 tmp = tmp.parent();
115 }
116 [allIndexes insertObject:@(qIdx.row()) atIndex:allIndexes.count];
117
118 NSUInteger indexes[allIndexes.count];
119 for (int i = 0 ; i < allIndexes.count ; ++i) {
120 indexes[i] = [[allIndexes objectAtIndex:i] intValue];
121 }
Alexandre Lision2db8f472015-07-22 15:05:46 -0400122 return [[NSIndexPath alloc] initWithIndexes:indexes length:allIndexes.count];
123}
124
125- (void) insertNodeAtQIndex:(QModelIndex) qIdx
126{
127 NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
128 //qDebug() << "insertNodeAt" << qIdx;
129 //NSLog(@"insertNodeAt index: %@", path);
Anthony LĂ©onard7f56bde2017-09-27 14:35:15 -0400130 if (path.length == 1 && [path indexAtPosition:0] <= [[[self arrangedObjects] childNodes] count])
Alexandre Lision2db8f472015-07-22 15:05:46 -0400131 [self insertObject:[[Node alloc] init] atArrangedObjectIndexPath:path];
132 else if (path.length > 1)
133 [self insertObject:[[Node alloc] init] atArrangedObjectIndexPath:path];
134}
135
136- (void) removeNodeAtQIndex:(QModelIndex) qIdx
137{
138 NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
139 if ([self.arrangedObjects descendantNodeAtIndexPath:path]) {
140 //NSLog(@"removeNodeAt index: %@", path);
141 [self removeObjectAtArrangedObjectIndexPath:path];
142 }
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400143}
144
Alexandre Lision89edc6a2015-11-09 11:30:47 -0500145- (void) setSelectionQModelIndex:(QModelIndex) qIdx
146{
147 NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
148 [self setSelectionIndexPath:path];
149}
150
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500151- (void)connect
152{
153 QObject::connect(self->privateQModel,
154 &QAbstractItemModel::rowsInserted,
155 [=](const QModelIndex & parent, int first, int last) {
Alexandre Lision2db8f472015-07-22 15:05:46 -0400156 for( int row = first; row <= last; ++row) {
157 //qDebug() << "INSERTING:"<< self->privateQModel->index(row, 0, parent) ;
158 if(!self->privateQModel->index(row, 0, parent).isValid())
159 continue;
160
161 [self insertNodeAtQIndex:self->privateQModel->index(row, 0, parent)];
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500162 }
Alexandre Lision2db8f472015-07-22 15:05:46 -0400163 });
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500164
165 QObject::connect(self->privateQModel,
166 &QAbstractItemModel::rowsAboutToBeMoved,
167 [=](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400168 //NSLog(@"rows about to be moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500169 /* first remove the row from old location
170 * then insert them at the new location on the "rowsMoved signal */
171 for( int row = sourceStart; row <= sourceEnd; row++) {
172 //TODO
173 }
Alexandre Lision2db8f472015-07-22 15:05:46 -0400174 });
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500175
176 QObject::connect(self->privateQModel,
177 &QAbstractItemModel::rowsMoved,
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400178 [self](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500179 for( int row = sourceStart; row <= sourceEnd; row++) {
Alexandre Lisionbfa68f62015-09-10 08:38:42 -0400180 NSIndexPath* srcPath = [self qIdxToNSIndexPath:self->privateQModel->index(row, 0, sourceParent)];
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400181 NSIndexPath* destPath = [self qIdxToNSIndexPath:self->privateQModel->index(destinationRow, 0, destinationParent)];
182
183 [self moveNode:[self.arrangedObjects descendantNodeAtIndexPath:srcPath] toIndexPath:destPath];
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500184 }
Alexandre Lision2db8f472015-07-22 15:05:46 -0400185 });
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500186
187 QObject::connect(self->privateQModel,
188 &QAbstractItemModel::rowsAboutToBeRemoved,
Alexandre Lision2db8f472015-07-22 15:05:46 -0400189 [self](const QModelIndex & parent, int first, int last) {
Alexandre Lision21666f32015-09-22 17:04:36 -0400190 for( int row = last; row >= first; --row) {
Alexandre Lision2db8f472015-07-22 15:05:46 -0400191 //qDebug() << "REMOVING:"<< self->privateQModel->index(row, 0, parent) ;
192 if (!self->privateQModel->index(row, 0, parent).isValid())
193 continue;
194
195 [self removeNodeAtQIndex:self->privateQModel->index(row, 0, parent)];
196 }
197 });
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500198
199 QObject::connect(self->privateQModel,
200 &QAbstractItemModel::rowsRemoved,
Alexandre Lision2db8f472015-07-22 15:05:46 -0400201 [self](const QModelIndex& parent, int first, int last) {
202
203 });
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500204
205 QObject::connect(self->privateQModel,
206 &QAbstractItemModel::layoutChanged,
Alexandre Lision2db8f472015-07-22 15:05:46 -0400207 [self]() {
Alexandre Lisionf5b90da2015-03-20 18:13:54 -0400208 //NSLog(@"layout changed");
Alexandre Lision2db8f472015-07-22 15:05:46 -0400209 [self rearrangeObjects];
210 });
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500211
Alexandre Lisionee098462015-10-22 17:22:50 -0400212 /* No way to 'update' a row, only insert/remove/move
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400213 QObject::connect(self->privateQModel,
214 &QAbstractItemModel::dataChanged,
Alexandre Lision2db8f472015-07-22 15:05:46 -0400215 [self](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400216 });
Alexandre Lisionee098462015-10-22 17:22:50 -0400217 */
Alexandre Lision5855b6a2015-02-03 11:31:05 -0500218}
219
220@end