QNSTreeController.mm 7.67 KB
Newer Older
1
/*
2
 *  Copyright (C) 2015-2016 Savoir-faire Linux Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */
19 20
#import "QNSTreeController.h"

21 22
#import <QDebug>

23 24 25 26 27 28 29 30 31 32 33 34 35 36
@interface Node : NSObject {
    NSMutableArray *children;
}
@end

@implementation Node
- (id) init
{
    if (self = [super init]) {
        children = [[NSMutableArray alloc] init];
    }
    return self;
}

37
- (void) addChild:(Node*) child AtIndex:(NSUInteger) idx
38
{
39 40 41 42 43 44
    [children insertObject:child atIndex:idx];
}

- (NSMutableArray*) children
{
    return children;
45 46 47 48 49 50 51 52 53
}

@end


@implementation QNSTreeController

- (id) initWithQModel:(QAbstractItemModel*) model
{
54
    self = [super init];
55 56
    self->privateQModel = model;

57 58 59
    NSMutableArray* nodes = [[NSMutableArray alloc] init];
    [self populate:nodes];

60
    [self connect];
61 62
    return [self initWithContent:nodes];
}
63

64 65 66 67 68 69 70 71
-(void) populate:(NSMutableArray*) nodes
{
    for (int i = 0 ; i < self->privateQModel->rowCount() ; ++i) {
        Node* n = [[Node alloc] init];
        //qDebug() << "POUPL TOP:"<< self->privateQModel->index(i, 0) ;
        [self populateChild:[n children] withParent:self->privateQModel->index(i, 0)];
        [nodes insertObject:n atIndex:i];
    }
72 73
}

74
- (void) populateChild:(NSMutableArray*) nodes withParent:(QModelIndex)qIdx
75
{
76 77 78 79 80 81
    if (!qIdx.isValid())
        return;
    for (int i = 0 ; i < self->privateQModel->rowCount(qIdx) ; ++i) {
        Node* n = [[Node alloc] init];
        [self populateChild:[n children] withParent:self->privateQModel->index(i, 0, qIdx)];
        [nodes insertObject:n atIndex:i];
82 83 84
    }
}

85 86 87 88 89
- (BOOL)isEditable
{
    return self->privateQModel->flags(self->privateQModel->index(0, 0)) | Qt::ItemIsEditable;
}

90
- (QModelIndex) indexPathtoQIdx:(NSIndexPath*) path
91
{
92 93
    NSUInteger myArray[[path length]];
    [path getIndexes:myArray];
94
    QModelIndex toReturn;
95

96
    for (int i = 0; i < path.length; ++i) {
97 98 99
        toReturn = self->privateQModel->index(myArray[i], 0, toReturn);
    }

100 101 102
    return toReturn;
}

103
- (QModelIndex) toQIdx:(NSTreeNode*) node
104
{
105 106
    return [self indexPathtoQIdx:node.indexPath];
}
107

108 109
- (NSIndexPath*) qIdxToNSIndexPath:(QModelIndex) qIdx
{
110 111 112 113 114 115 116 117 118 119 120 121
    QModelIndex tmp = qIdx.parent();
    NSMutableArray* allIndexes = [NSMutableArray array];
    while (tmp.isValid()) {
        [allIndexes insertObject:@(tmp.row()) atIndex:0];
        tmp = tmp.parent();
    }
    [allIndexes insertObject:@(qIdx.row()) atIndex:allIndexes.count];

    NSUInteger indexes[allIndexes.count];
    for (int i = 0 ; i < allIndexes.count ; ++i) {
        indexes[i] = [[allIndexes objectAtIndex:i] intValue];
    }
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
    return [[NSIndexPath alloc] initWithIndexes:indexes length:allIndexes.count];
}

- (void) insertNodeAtQIndex:(QModelIndex) qIdx
{
    NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
    //qDebug() << "insertNodeAt" << qIdx;
    //NSLog(@"insertNodeAt index: %@", path);
    if (path.length == 1 && [path indexAtPosition:0] <= [[self arrangedObjects] count])
        [self insertObject:[[Node alloc] init] atArrangedObjectIndexPath:path];
    else if (path.length > 1)
        [self insertObject:[[Node alloc] init] atArrangedObjectIndexPath:path];
}

- (void) removeNodeAtQIndex:(QModelIndex) qIdx
{
    NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
    if ([self.arrangedObjects descendantNodeAtIndexPath:path]) {
        //NSLog(@"removeNodeAt index: %@", path);
        [self removeObjectAtArrangedObjectIndexPath:path];
    }
143 144
}

145 146 147 148 149 150
- (void) setSelectionQModelIndex:(QModelIndex) qIdx
{
    NSIndexPath* path = [self qIdxToNSIndexPath:qIdx];
    [self setSelectionIndexPath:path];
}

151 152 153 154 155
- (void)connect
{
    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsInserted,
                     [=](const QModelIndex & parent, int first, int last) {
156 157 158 159 160 161
                         for( int row = first; row <= last; ++row) {
                             //qDebug() << "INSERTING:"<< self->privateQModel->index(row, 0, parent) ;
                             if(!self->privateQModel->index(row, 0, parent).isValid())
                                 continue;

                             [self insertNodeAtQIndex:self->privateQModel->index(row, 0, parent)];
162
                         }
163
                     });
164 165 166 167

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsAboutToBeMoved,
                     [=](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
168
                        //NSLog(@"rows about to be moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
169 170 171 172 173
                        /* first remove the row from old location
                          * then insert them at the new location on the "rowsMoved signal */
                         for( int row = sourceStart; row <= sourceEnd; row++) {
                             //TODO
                         }
174
                     });
175 176 177

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsMoved,
178
                     [self](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
179
                         for( int row = sourceStart; row <= sourceEnd; row++) {
180
                             NSIndexPath* srcPath = [self qIdxToNSIndexPath:self->privateQModel->index(row, 0, sourceParent)];
181 182 183
                             NSIndexPath* destPath = [self qIdxToNSIndexPath:self->privateQModel->index(destinationRow, 0, destinationParent)];

                             [self moveNode:[self.arrangedObjects descendantNodeAtIndexPath:srcPath] toIndexPath:destPath];
184
                         }
185
                     });
186 187 188

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsAboutToBeRemoved,
189
                     [self](const QModelIndex & parent, int first, int last) {
190
                         for( int row = last; row >= first; --row) {
191 192 193 194 195 196 197
                             //qDebug() << "REMOVING:"<< self->privateQModel->index(row, 0, parent) ;
                             if (!self->privateQModel->index(row, 0, parent).isValid())
                                 continue;

                             [self removeNodeAtQIndex:self->privateQModel->index(row, 0, parent)];
                         }
                     });
198 199 200

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::rowsRemoved,
201 202 203
                     [self](const QModelIndex& parent, int first, int last) {

                     });
204 205 206

    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::layoutChanged,
207
                     [self]() {
208
                         //NSLog(@"layout changed");
209 210
                         [self rearrangeObjects];
                     });
211

212
    /* No way to 'update' a row, only insert/remove/move
213 214
    QObject::connect(self->privateQModel,
                     &QAbstractItemModel::dataChanged,
215
                     [self](const QModelIndex &topLeft, const QModelIndex &bottomRight) {
216
                     });
217
    */
218 219 220
}

@end