Projet

Général

Profil

Paste
Statistiques
| Branche: | Révision:

ryxeo-webphotoalbum-git / mymodel.cpp @ 71c02254

Historique | Voir | Annoter | Télécharger (19,9 ko)

1
/****************************************************************************
2
*
3
* This file is part of qtFM, a simple, fast file manager.
4
* Copyright (C) 2010,2011 Wittfella
5
*
6
* This file is a local adaptation for RyXeo TagFile System
7
* Copyright (C) 2012 Eric Seigne <eric.seigne@ryxeo.com>
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program.  If not, see <http://www.gnu.org/licenses/>
21
*
22
* Contact e-mail: wittfella@qtfm.org
23
*
24
****************************************************************************/
25

    
26

    
27
#include "mymodel.h"
28
#include <unistd.h>
29
#include <sys/ioctl.h>
30

    
31
//---------------------------------------------------------------------------------
32
myModel::myModel()
33
{
34
    mimeGeneric = new QHash<QString,QString>;
35
    mimeGlob = new QHash<QString,QString>;
36
    mimeIcons = new QHash<QString,QIcon>;
37
    folderIcons = new QHash<QString,QIcon>;
38
    thumbs = new QHash<QString,QByteArray>;
39
    icons = new QHash<QString,QIcon>;
40

    
41
    QFile fileIcons(QDir::homePath() + "/.config/ryxeo/file.cache");
42
    fileIcons.open(QIODevice::ReadOnly);
43
    QDataStream out(&fileIcons);
44
    out >> *mimeIcons;
45
    fileIcons.close();
46

    
47
    fileIcons.setFileName(QDir::homePath() + "/.config/ryxeo/folder.cache");
48
    fileIcons.open(QIODevice::ReadOnly);
49
    out.setDevice(&fileIcons);
50
    out >> *folderIcons;
51
    fileIcons.close();
52

    
53
    rootItem = new myModelItem(QFileInfo("/"),new myModelItem(QFileInfo(),0));
54

    
55
    currentRootPath = "/";
56

    
57
    QDir root("/");
58
    QFileInfoList drives = root.entryInfoList(QDir::AllEntries | QDir::Files | QDir::NoDotAndDotDot);
59

    
60
    foreach(QFileInfo drive, drives)
61
        new myModelItem(drive,rootItem);
62

    
63
    rootItem->walked = true;
64
    rootItem = rootItem->parent();
65

    
66
    iconFactory = new QFileIconProvider();
67
}
68

    
69
//---------------------------------------------------------------------------------------
70
myModel::~myModel()
71
{
72
    delete rootItem;
73
    delete iconFactory;
74
}
75

    
76
//---------------------------------------------------------------------------------------
77
QModelIndex myModel::index(int row, int column, const QModelIndex &parent) const
78
{
79
    if(parent.isValid() && parent.column() != 0)
80
        return QModelIndex();
81

    
82
    myModelItem *parentItem = static_cast<myModelItem*>(parent.internalPointer());
83
    if(!parentItem) parentItem = rootItem;
84

    
85
    myModelItem *childItem = parentItem->childAt(row);
86
        if(childItem) return createIndex(row, column, childItem);
87

    
88
    return QModelIndex();
89
}
90

    
91
//---------------------------------------------------------------------------------------
92
QModelIndex myModel::index(const QString& path) const
93
{
94
//    qDebug() << "myModel::index " << path;
95

    
96
    myModelItem *item = rootItem->matchPath(path.split(SEPARATOR),0);
97

    
98
    if(item) return createIndex(item->childNumber(),0,item);
99

    
100
    return QModelIndex();
101
}
102

    
103
//---------------------------------------------------------------------------------------
104
QModelIndex myModel::parent(const QModelIndex &index) const
105
{
106
    if(!index.isValid()) return QModelIndex();
107

    
108
    myModelItem *childItem = static_cast<myModelItem*>(index.internalPointer());
109

    
110
    if(!childItem) return QModelIndex();
111

    
112
    myModelItem *parentItem = childItem->parent();
113

    
114
    if (!parentItem || parentItem == rootItem) return QModelIndex();
115

    
116
    return createIndex(parentItem->childNumber(), 0, parentItem);
117
}
118

    
119
//---------------------------------------------------------------------------------------
120
QFileInfo myModel::fileInfo(const QModelIndex &index)
121
{
122
    myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
123

    
124
    if(item) return item->fileInfo();
125

    
126
    return QFileInfo();
127
}
128

    
129
//---------------------------------------------------------------------------------------
130
qint64 myModel::size(const QModelIndex &index)
131
{
132
    myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
133

    
134
    if(item) return item->fileInfo().size();
135

    
136
    return 0;
137
}
138

    
139
//---------------------------------------------------------------------------------------
140
QString myModel::fileName(const QModelIndex &index)
141
{
142
    myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
143

    
144
    if(item) return item->fileName();
145

    
146
    return "";
147
}
148

    
149
//---------------------------------------------------------------------------------------
150
QString myModel::filePath(const QModelIndex &index)
151
{
152
    myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
153

    
154
    if(item) return item->fileInfo().filePath();
155

    
156
    return false;
157
}
158

    
159
//---------------------------------------------------------------------------------
160
bool myModel::setRootPath(const QString& path)
161
{
162
    qDebug() << "Changement de rootPath " << path;
163
    currentRootPath = path;
164

    
165
    myModelItem *item = rootItem->matchPath(path.split(SEPARATOR));
166

    
167
    if(item->walked == 0)
168
    {
169
        populateItem(item);
170
        return false;
171
    }
172
    else
173
    if(item->dirty)                         //model is up to date, but view needs to be invalidated
174
    {
175
        item->dirty = 0;
176
        return true;
177
    }
178

    
179
    return false;
180
}
181

    
182
void myModel::populateItem(QString nomFichier)
183
{
184
//    qDebug() << "populateItem:: " << nomFichier << " :: " << rootItem->absoluteFilePath();
185
    beginInsertRows(index(rootItem->absoluteFilePath()),rootItem->childCount(),rootItem->childCount());
186
    new myModelItem(QFileInfo(nomFichier),rootItem);
187
    endInsertRows();
188
}
189

    
190
//---------------------------------------------------------------------------------------
191
void myModel::populateItem(myModelItem *item)
192
{
193
//    qDebug() << "myModel::populateItem(1) : " << item->fileInfo().absolutePath() << " (" << currentRootPath << ")";
194
    item->walked = 1;
195

    
196
    QDir dir(item->absoluteFilePath());
197
    QFileInfoList all = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
198

    
199
//    addWatcher(item);
200

    
201
    foreach(QFileInfo one, all)
202
        new myModelItem(one,item);
203
//    qDebug() << "myModel::populateItem :" << item->absoluteFilePath();
204
}
205

    
206
//---------------------------------------------------------------------------------
207
int myModel::columnCount(const QModelIndex &parent) const
208
{
209
    return (parent.column() > 0) ? 0 : 5;
210
}
211

    
212
//---------------------------------------------------------------------------------------
213
int myModel::rowCount(const QModelIndex &parent) const
214
{
215
    myModelItem *item = static_cast<myModelItem*>(parent.internalPointer());
216
    if(item) return item->childCount();
217
    return rootItem->childCount();
218
}
219

    
220
//---------------------------------------------------------------------------------
221
void myModel::clear()
222
{
223
    beginResetModel();
224
    rootItem->clearAll();
225
    endResetModel();
226
}
227

    
228
//---------------------------------------------------------------------------------
229
QModelIndex myModel::insertFile(QModelIndex parent)
230
{
231
    myModelItem *item = static_cast<myModelItem*>(parent.internalPointer());
232

    
233
    int num = 0;
234
    QString name;
235

    
236
    do
237
    {
238
        num++;
239
        name = QString("new_file%1").arg(num);
240
    }
241
    while (item->hasChild(name));
242

    
243

    
244
    QFile temp(currentRootPath + "/" + name);
245
    if(!temp.open(QIODevice::WriteOnly)) return QModelIndex();
246
    temp.close();
247

    
248
    beginInsertRows(parent,item->childCount(),item->childCount());
249
    new myModelItem(QFileInfo(temp),item);
250
    endInsertRows();
251

    
252
    return index(item->childCount()-1,0,parent);
253
}
254

    
255
//---------------------------------------------------------------------------------
256
Qt::DropActions myModel::supportedDropActions() const
257
{
258
    return Qt::CopyAction | Qt::MoveAction;
259
}
260

    
261
//---------------------------------------------------------------------------------
262
QStringList myModel::mimeTypes() const
263
{
264
    return QStringList("text/uri-list");
265
}
266

    
267
//---------------------------------------------------------------------------------
268
QMimeData * myModel::mimeData(const QModelIndexList & indexes) const
269
{
270
    QMimeData *data = new QMimeData();
271

    
272
    QList<QUrl> files;
273

    
274
    foreach(QModelIndex index, indexes)
275
    {
276
        myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
277
        files.append(QUrl::fromLocalFile(item->absoluteFilePath()));
278
    }
279

    
280
    data->setUrls(files);
281
    return data;
282
}
283

    
284

    
285
//---------------------------------------------------------------------------------
286
void myModel::cacheInfo()
287
{
288
    QFile fileIcons(QDir::homePath() + "/.config/ryxeo/file.cache");
289
    fileIcons.open(QIODevice::WriteOnly);
290
    QDataStream out(&fileIcons);
291
    out << *mimeIcons;
292
    fileIcons.close();
293

    
294
    fileIcons.setFileName(QDir::homePath() + "/.config/ryxeo/folder.cache");
295
    fileIcons.open(QIODevice::WriteOnly);
296
    out.setDevice(&fileIcons);
297
    out << *folderIcons;
298
    fileIcons.close();
299

    
300
    if(thumbs->count() > thumbCount)
301
    {
302
        fileIcons.setFileName(QDir::homePath() + "/.config/ryxeo/thumbs.cache");
303
        fileIcons.open(QIODevice::WriteOnly);
304
        out.setDevice(&fileIcons);
305
        out << *thumbs;
306
        fileIcons.close();
307
    }
308
}
309

    
310
//---------------------------------------------------------------------------------
311
void myModel::setMode(bool icons)
312
{
313
    showThumbs = icons;
314
}
315

    
316
//---------------------------------------------------------------------------------
317
void myModel::loadMimeTypes() const
318
{
319
    QFile mimeInfo("/usr/share/mime/globs");
320
    mimeInfo.open(QIODevice::ReadOnly);
321
    QTextStream out(&mimeInfo);
322

    
323
    do
324
    {
325
        QStringList line = out.readLine().split(":");
326
        if(line.count() == 2)
327
        {
328
            QString suffix = line.at(1);
329
            suffix.remove("*.");
330
            QString mimeName = line.at(0);
331
            mimeName.replace("/","-");
332
            mimeGlob->insert(suffix,mimeName);
333
        }
334
    }
335
    while (!out.atEnd());
336

    
337
    mimeInfo.close();
338

    
339
    mimeInfo.setFileName("/usr/share/mime/generic-icons");
340
    mimeInfo.open(QIODevice::ReadOnly);
341
    out.setDevice(&mimeInfo);
342

    
343
    do
344
    {
345
        QStringList line = out.readLine().split(":");
346
        if(line.count() == 2)
347
        {
348
            QString mimeName = line.at(0);
349
            mimeName.replace("/","-");
350
            QString icon = line.at(1);
351
            mimeGeneric->insert(mimeName,icon);
352
        }
353
    }
354
    while (!out.atEnd());
355

    
356
    mimeInfo.close();
357
}
358

    
359
//---------------------------------------------------------------------------
360
void myModel::loadThumbsQSL(QStringList indexes)
361
{
362
//    qDebug() << "myModel::loadThumbsQSL (1)" << indexes;
363
    QStringList files,types;
364
    types << "jpg" << "jpeg" << "png" << "bmp" << "ico" << "svg" << "gif";
365

    
366
    foreach(QString item,indexes) {
367
        if(types.contains(QFileInfo(item).suffix(),Qt::CaseInsensitive)) {
368
            files.append(item);
369
        }
370
    }
371

    
372
//    qDebug() << "loadThumbs pour " << files;
373

    
374
    if(files.count())
375
    {
376
        if(thumbs->count() == 0)
377
        {
378
            QFile fileIcons(QDir::homePath() + "/.config/ryxeo/thumbs.cache");
379
            fileIcons.open(QIODevice::ReadOnly);
380
            QDataStream out(&fileIcons);
381
            out >> *thumbs;
382
            fileIcons.close();
383
            thumbCount = thumbs->count();
384
        }
385

    
386
        foreach(QString item, files)
387
        {
388
            if(!thumbs->contains(item)) thumbs->insert(item,getThumb(item));
389
            emit thumbUpdate(index(item));
390
        }
391
    }
392

    
393
}
394

    
395
//---------------------------------------------------------------------------
396
QByteArray myModel::getThumb(QString item)
397
{
398
    qDebug() << "Creation du thumbnail pour " << item;
399
    QImage theThumb, background;
400
    QImageReader pic(item);
401
    int w,h,target;
402
    w = pic.size().width();
403
    h = pic.size().height();
404

    
405
    if( w > 128 || h > 128)
406
    {
407
        target = 114;
408
        background.load(":/images/background.jpg");
409
    }
410
    else
411
    {
412
        target = 64;
413
        background = QImage(128,128,QImage::Format_ARGB32);
414
        background.fill(QApplication::palette().color(QPalette::Base).rgb());
415
    }
416

    
417
    if(w > h)
418
    {
419
        int newHeight = h * target / w;
420
        pic.setScaledSize(QSize(target,newHeight));
421
    }
422
    else
423
    {
424
        int newWidth = w * target / h;
425
        pic.setScaledSize(QSize(newWidth,target));
426
    }
427

    
428
    theThumb = pic.read();
429

    
430
    int thumbWidth = theThumb.width();
431
    int thumbHeight = theThumb.height();
432

    
433
    QPainter painter(&background);
434
    painter.drawImage(QPoint((128-thumbWidth)/2,(128 - thumbHeight)/2),theThumb);
435

    
436
    QBuffer buffer;
437
    QImageWriter writer(&buffer,"jpg");
438
    writer.setQuality(50);
439
    writer.write(background);
440

    
441
    return buffer.buffer();
442
}
443

    
444
//---------------------------------------------------------------------------------
445
QVariant myModel::data(const QModelIndex & index, int role) const
446
{
447
    myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
448

    
449
    if(role == Qt::ForegroundRole)
450
    {
451
        QFileInfo type(item->fileInfo());
452

    
453
        if(cutItems.contains(type.filePath())) return QBrush(QColor(Qt::lightGray));
454
        if(type.isHidden()) return QBrush(QColor(Qt::darkGray));
455
        if(type.isSymLink()) return QBrush(QColor(Qt::blue));
456
        if(type.isDir()) return QBrush(QColor(Qt::black));
457
        if(type.isExecutable()) return QBrush(QColor(Qt::darkGreen));
458
    }
459
    else
460
    if(role == Qt::TextAlignmentRole)
461
    {
462
        if(index.column() == 1) return Qt::AlignRight + Qt::AlignVCenter;
463
    }
464
    else
465
    if(role == Qt::DisplayRole)
466
    {
467
        QVariant data;
468
        switch(index.column())
469
        {
470
            case 0:
471
                data = item->fileName();
472
                break;
473
            case 1:
474
                if(item->fileInfo().isDir()) data = "";
475
                else data = formatSize(item->fileInfo().size());
476
                break;
477
            case 2:
478
                if(item->fileInfo().isDir()) data = "folder";
479
                else data = item->fileInfo().suffix();
480
                if(data == "") data = "file";
481
                break;
482
            case 3:
483
                data = item->fileInfo().lastModified().toString(Qt::LocalDate);
484
                break;
485
            case 4:
486
                {
487
                    QString str;
488

    
489
                    QFlags<QFile::Permissions> perms = item->fileInfo().permissions();
490
                    if(perms.testFlag(QFile::ReadOwner)) str.append("r"); else str.append(("-"));
491
                    if(perms.testFlag(QFile::WriteOwner)) str.append("w"); else str.append(("-"));
492
                    if(perms.testFlag(QFile::ExeOwner)) str.append("x"); else str.append(("-"));
493
                    if(perms.testFlag(QFile::ReadGroup)) str.append("r"); else str.append(("-"));
494
                    if(perms.testFlag(QFile::WriteGroup)) str.append("w"); else str.append(("-"));
495
                    if(perms.testFlag(QFile::ExeGroup)) str.append("x"); else str.append(("-"));
496
                    if(perms.testFlag(QFile::ReadOther)) str.append("r"); else str.append(("-"));
497
                    if(perms.testFlag(QFile::WriteOther)) str.append("w"); else str.append(("-"));
498
                    if(perms.testFlag(QFile::ExeOther)) str.append("x"); else str.append(("-"));
499
                    str.append(" " + item->fileInfo().owner() + " " + item->fileInfo().group());
500
                    return str;
501
                }
502
            default:
503
                data = "";
504
                break;
505
        }
506
        return data;
507
    }
508
    else
509
    if(role == Qt::DecorationRole)
510
    {
511
        if(index.column() != 0) return QVariant();
512

    
513
        QFileInfo type(item->fileInfo());
514

    
515
        if(type.isDir())
516
        {
517
            if(folderIcons->contains(type.fileName())) return folderIcons->value(type.fileName());
518
            return iconFactory->icon(type);
519
        }
520
        else
521
        {
522
            if(showThumbs)
523
            {
524
                if(icons->contains(item->absoluteFilePath())) return icons->value(item->absoluteFilePath());
525
                else
526
                    if(thumbs->contains(type.filePath()))
527
                    {
528
                        QPixmap pic;
529
                        pic.loadFromData(thumbs->value(item->absoluteFilePath()));
530
                        icons->insert(item->absoluteFilePath(),QIcon(pic));
531
                        return icons->value(item->absoluteFilePath());
532
                    }
533
            }
534

    
535
            QString suffix = type.suffix();
536
            if(mimeIcons->contains(suffix)) return mimeIcons->value(suffix);
537

    
538
            QIcon theIcon;
539

    
540
            if(suffix.isEmpty())
541
            {
542
                if(type.isExecutable()) suffix = "exec";
543
                else suffix = "none";
544

    
545
                if(mimeIcons->contains(suffix)) return mimeIcons->value(suffix);
546

    
547
                if(suffix == "exec") theIcon = QIcon::fromTheme("application-x-executable");
548
                else theIcon = QIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon));
549
             }
550
            else
551
            {
552
                if(mimeGlob->count() == 0) loadMimeTypes();
553

    
554
                //try mimeType as it is
555
                QString mimeType = mimeGlob->value(type.suffix().toLower());
556
                if(QIcon::hasThemeIcon(mimeType)) theIcon = QIcon::fromTheme(mimeType);
557
                else
558
                {
559
                    //try matching generic icon
560
                    if(QIcon::hasThemeIcon(mimeGeneric->value(mimeType))) theIcon = QIcon::fromTheme(mimeGeneric->value(mimeType));
561
                    else
562
                    {
563
                        //last resort try adding "-x-generic" to base type
564
                        if(QIcon::hasThemeIcon(mimeType.split("-").at(0) + "-x-generic")) theIcon = QIcon::fromTheme(mimeType.split("-").at(0) + "-x-generic");
565
                        else theIcon = QIcon(qApp->style()->standardIcon(QStyle::SP_FileIcon));
566
                    }
567
                }
568
            }
569

    
570
            mimeIcons->insert(suffix,theIcon);
571
            return theIcon;
572
        }
573
    }
574
    else
575
    if(role == Qt::EditRole)
576
    {
577
        return item->fileName();
578
    }
579
//    if(role == Qt::StatusTipRole)
580
//    {
581
//        return item->fileName();
582
//    }
583

    
584
    return QVariant();
585
}
586

    
587
//---------------------------------------------------------------------------------
588
bool myModel::setData(const QModelIndex & index, const QVariant & value, int role)
589
{
590
    //can only set the filename
591
    myModelItem *item = static_cast<myModelItem*>(index.internalPointer());
592

    
593
    //physically change the name on disk
594
    bool ok = QFile::rename(item->absoluteFilePath(),item->parent()->absoluteFilePath() + SEPARATOR + value.toString());
595

    
596
    //change the details in the modelItem
597
    if(ok)
598
    {
599
        item->changeName(value.toString());
600
        emit dataChanged(index,index);
601
    }
602

    
603
    return ok;
604
}
605

    
606
//---------------------------------------------------------------------------------
607
QVariant myModel::headerData(int section, Qt::Orientation orientation, int role) const
608
{
609
    if(role == Qt::DisplayRole)
610
        switch(section)
611
        {
612
        case 0: return tr("Name");
613
        case 1: return tr("Size");
614
        case 2: return tr("Type");
615
        case 4: return tr("Owner");
616
        case 3: return tr("Date Modified");
617
            default: return QVariant();
618
        }
619

    
620
    return QVariant();
621
}
622

    
623
//---------------------------------------------------------------------------------------
624
Qt::ItemFlags myModel::flags(const QModelIndex &index) const
625
{
626
    if(!index.isValid()) return 0;
627
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
628
}
629

    
Redmine Appliance - Powered by TurnKey Linux