Projet

Général

Profil

Révision 71c02254

Voir les différences:

mymodel.cpp
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

  
mymodel.h
1
/****************************************************************************
2
* This file is part of qtFM, a simple, fast file manager.
3
* Copyright (C) 2010,2011 Wittfella
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 2 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, see <http://www.gnu.org/licenses/>
17
*
18
* Contact e-mail: wittfella@qtfm.org
19
*
20
****************************************************************************/
21

  
22

  
23
#ifndef MYMODEL_H
24
#define MYMODEL_H
25

  
26
#include <QtGui>
27
#include "mymodelitem.h"
28

  
29
QString formatSize(qint64);
30

  
31

  
32
class myModel : public QAbstractItemModel
33
{
34
    Q_OBJECT
35

  
36
public:
37
        myModel();
38
        ~myModel();
39

  
40
        void loadMimeTypes() const;
41
        void cacheInfo();
42
        void setMode(bool);
43
        void loadThumbsQSL(QStringList);
44
        void populateItem(QString nomFichier);
45
        void populateItem(myModelItem *item);
46
        void clear();
47

  
48
        bool setRootPath(const QString& path);
49

  
50
        QModelIndex index(int row, int column, const QModelIndex &parent) const;
51
        QModelIndex index(const QString& path) const;
52
        QModelIndex parent(const QModelIndex &index) const;
53
        QModelIndex insertFile(QModelIndex parent);
54

  
55
        int rowCount(const QModelIndex &parent) const;
56
        qint64 size(const QModelIndex &index);
57

  
58
        QString fileName(const QModelIndex &index);
59
        QString filePath(const QModelIndex &index);
60

  
61
        QStringList mimeTypes() const;
62

  
63
        QByteArray getThumb(QString item);
64

  
65
        QFileInfo fileInfo(const QModelIndex &index);
66

  
67
        Qt::DropActions supportedDropActions () const;
68
        QMimeData * mimeData(const QModelIndexList & indexes) const;
69

  
70
        QHash<QString,QIcon> *mimeIcons;
71
        QHash<QString,QIcon> *folderIcons;
72
        QHash<QString,QIcon> *icons;
73

  
74
signals:
75
        void dragDropPaste(const QMimeData * data, QString newPath, QStringList cutList);
76
        void thumbUpdate(const QModelIndex index);
77

  
78
protected:
79
        QVariant data(const QModelIndex & index, int role) const;
80
        QVariant headerData(int section, Qt::Orientation orientation, int role) const;
81
        bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);
82
        int columnCount(const QModelIndex &parent) const;
83

  
84
        Qt::ItemFlags flags(const QModelIndex &index) const;
85

  
86
private:
87

  
88
        bool showThumbs;
89
        int thumbCount;
90
        QStringList cutItems;
91
        QHash<QString,QString> *mimeGlob;
92
        QHash<QString,QString> *mimeGeneric;
93
        QHash<QString,QByteArray> *thumbs;
94

  
95
        myModelItem* rootItem;
96
        QString currentRootPath;
97
        QFileIconProvider* iconFactory;
98

  
99
        QHash<int, QString> watchers;
100
};
101

  
102
//---------------------------------------------------------------------------------
103
// Global functions.
104
//---------------------------------------------------------------------------------
105
QString formatSize(qint64);
106

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

  
25
#include "mymodelitem.h"
26
#include <QtGui>
27

  
28

  
29
//---------------------------------------------------------------------------------------
30
myModelItem::myModelItem(const QFileInfo& fileInfo, myModelItem* parent)
31
{
32
    mParent = parent;
33
    mFileInfo = fileInfo;
34
    walked = false;
35
    dirty = false;
36

  
37
    if(parent)
38
    {
39
          parent->addChild(this);
40
          mAbsFilePath = fileInfo.filePath();
41
    }
42
    else
43
    {
44
        walked = true;
45
        mAbsFilePath = "";
46
    }
47
}
48

  
49
//---------------------------------------------------------------------------------------
50
myModelItem::~myModelItem()
51
{
52
    qDeleteAll(mChildren);
53
}
54

  
55
//---------------------------------------------------------------------------------------
56
myModelItem* myModelItem::childAt(int position)
57
{
58
    return mChildren.value(position,0);
59
}
60

  
61
//---------------------------------------------------------------------------------------
62
int myModelItem::childCount() const
63
{
64
    if(walked) return mChildren.count();
65
    return 1;
66
}
67

  
68
//---------------------------------------------------------------------------------------
69
bool myModelItem::hasChild(QString fileName)
70
{
71
    foreach(myModelItem * item, mChildren)
72
        if(item->fileName() == fileName) return true;
73

  
74
    return false;
75
}
76

  
77
//---------------------------------------------------------------------------------------
78
int myModelItem::childNumber() const
79
{
80
    if(mParent)
81
    {
82
      return mParent->mChildren.indexOf(const_cast<myModelItem*>(this));
83
    }
84

  
85
    return 0;
86
}
87

  
88
//---------------------------------------------------------------------------------------
89
QList<myModelItem*> myModelItem::children()
90
{
91
    return mChildren;
92
}
93

  
94
//---------------------------------------------------------------------------------------
95
myModelItem* myModelItem::parent()
96
{
97
    return mParent;
98
}
99

  
100
//---------------------------------------------------------------------------------------
101
QString myModelItem::absoluteFilePath()const
102
{
103
    return mAbsFilePath;
104
}
105

  
106
//---------------------------------------------------------------------------------------
107
QString myModelItem::fileName() const
108
{
109
    if(mAbsFilePath == "/") return "/";
110
    else return mFileInfo.fileName();
111

  
112
}
113

  
114
//---------------------------------------------------------------------------------------
115
QFileInfo myModelItem::fileInfo() const
116
{
117
    return mFileInfo;
118
}
119

  
120
//---------------------------------------------------------------------------------------
121
void myModelItem::refreshFileInfo()
122
{
123
    mFileInfo.refresh();
124
}
125

  
126
//---------------------------------------------------------------------------------------
127
void myModelItem::addChild(myModelItem *child)
128
{
129
    if(!mChildren.contains(child))
130
    {
131
      mChildren.append(child);
132
    }
133
}
134

  
135
//---------------------------------------------------------------------------------------
136
void myModelItem::removeChild(myModelItem *child)
137
{
138
    mChildren.removeOne(child);
139
    delete child;
140
}
141

  
142
//---------------------------------------------------------------------------------------
143
void myModelItem::clearAll()
144
{
145
    foreach(myModelItem *child, mChildren)
146
        delete child;
147
    mChildren.clear();
148
    walked = 0;
149
}
150

  
151
//---------------------------------------------------------------------------------------
152
void myModelItem::changeName(QString newName)
153
{
154
    mAbsFilePath = mParent->absoluteFilePath() + SEPARATOR + newName;
155
    mFileInfo.setFile(mAbsFilePath);
156
    clearAll();
157
}
158

  
159
//---------------------------------------------------------------------------------------
160
myModelItem* myModelItem::matchPath(const QStringList& path, int startIndex)
161
{
162
    QStringList temp = path;
163
    temp.replace(0,"/");
164
    temp.removeAll("");
165

  
166
    if(walked == 0)     //not populated yet
167
    {
168
        walked = true;
169
    }
170

  
171
    foreach(myModelItem* child, mChildren)
172
    {
173
        QString match = temp.at(startIndex);
174

  
175
        if(child->fileName() == match)
176
        {
177
            if(startIndex + 1 == temp.count()) return child;
178
            else return child->matchPath(path,startIndex + 1);
179
        }
180
    }
181

  
182
    return 0;
183
}
184

  
185
//---------------------------------------------------------------------------------------
186

  
187

  
mymodelitem.h
1
/****************************************************************************
2
* This file is part of qtFM, a simple, fast file manager.
3
* Copyright (C) 2010,2011 Wittfella
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 2 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, see <http://www.gnu.org/licenses/>
17
*
18
* Contact e-mail: wittfella@qtfm.org
19
*
20
****************************************************************************/
21

  
22
#ifndef MYMODELITEM_H
23
#define MYMODELITEM_H
24

  
25
#include <QDir>
26
#include <QFileIconProvider>
27
#include <QDateTime>
28

  
29
#define SEPARATOR QString("/")
30

  
31

  
32

  
33
class myModelItem
34
{
35

  
36
public:
37

  
38
    myModelItem(const QFileInfo& fileInfo, myModelItem* parent);
39
    ~myModelItem();
40

  
41
    myModelItem* childAt(int position);
42
    myModelItem* parent();
43
    myModelItem* matchPath(const QStringList& path, int startIndex = 0);
44

  
45
    QList<myModelItem*> children();
46

  
47
    int childCount() const;
48
    int childNumber() const;
49
    bool hasChild(QString);
50

  
51
    QString absoluteFilePath() const;
52
    QString fileName() const;
53

  
54
    QFileInfo fileInfo() const;
55

  
56
    void refreshFileInfo();
57
    void addChild(myModelItem *child);
58
    void removeChild(myModelItem *child);
59
    void changeName(QString);
60
    void clearAll();
61

  
62
    bool walked;
63
    bool dirty;
64

  
65
private:
66

  
67
    QList<myModelItem*> mChildren;
68
    myModelItem* mParent;
69
    QFileInfo mFileInfo;
70
    QString mAbsFilePath;
71
};
72

  
73

  
74
#endif // MYMODELITEM_H
original.cpp
24 24
#include "original.h"
25 25
#include "ui_original.h"
26 26

  
27

  
28
//---------------------------------------------------------------------------------
29
bool viewsSortProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
30
{
31
    if(this->filterRegExp().isEmpty()) return true;
32

  
33
    QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
34
    myModel* fileModel = qobject_cast<myModel*>(sourceModel());
35

  
36
    if(fileModel->fileInfo(index0).isHidden()) return false;
37
    else return true;
38
}
39

  
40

  
41
//---------------------------------------------------------------------------------
42
bool viewsSortProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
43
{
44
    myModel* fsModel = dynamic_cast<myModel*>(sourceModel());
45

  
46
    if(left.column() == 1)          //size
47
    {
48
        if(fsModel->size(left) > fsModel->size(right)) return true;
49
        else return false;
50
    }
51
    else
52
    if(left.column() == 3)          //date
53
    {
54
        if(fsModel->fileInfo(left).lastModified() > fsModel->fileInfo(right).lastModified()) return true;
55
        else return false;
56
    }
57

  
58
    return QSortFilterProxyModel::lessThan(left,right);
59
}
60

  
61
//---------------------------------------------------------------------------------
62
QStringList myCompleter::splitPath(const QString& path) const
63
{
64
    QStringList parts = path.split("/");
65
    parts[0] = "/";
66

  
67
    return parts;
68
}
69

  
70
//---------------------------------------------------------------------------------
71
QString myCompleter::pathFromIndex(const QModelIndex& index) const
72
{
73
    if(!index.isValid()) return "";
74

  
75
    QModelIndex idx = index;
76
    QStringList list;
77
    do
78
    {
79
        QString t = model()->data(idx, Qt::EditRole).toString();
80
        list.prepend(t);
81
        QModelIndex parent = idx.parent();
82
        idx = parent.sibling(parent.row(), index.column());
83
    }
84
    while (idx.isValid());
85

  
86
    list[0].clear() ; // the join below will provide the separator
87

  
88
    return list.join("/");
89
}
90

  
91
//---------------------------------------------------------------------------
92
QString formatSize(qint64 num)
93
{
94
    QString total;
95
    const qint64 kb = 1024;
96
    const qint64 mb = 1024 * kb;
97
    const qint64 gb = 1024 * mb;
98
    const qint64 tb = 1024 * gb;
99

  
100
    if (num >= tb) total = QString("%1TB").arg(QString::number(qreal(num) / tb, 'f', 2));
101
    else if(num >= gb) total = QString("%1GB").arg(QString::number(qreal(num) / gb, 'f', 2));
102
    else if(num >= mb) total = QString("%1MB").arg(QString::number(qreal(num) / mb, 'f', 1));
103
    else if(num >= kb) total = QString("%1KB").arg(QString::number(qreal(num) / kb,'f', 1));
104
    else total = QString("%1 bytes").arg(num);
105

  
106
    return total;
107
}
108

  
109
// =========================================================================================================================
110

  
111

  
27 112
original::original(QWidget *parent) :
28 113
    QMainWindow(parent),
29 114
    ui(new Ui::original)
......
165 250
        ui->statusBar->showMessage(trUtf8("Fichier en cours: %1 [hq] [mq] [lq] [meta] ... terminé").arg(list.at(i).fileName()),3000);
166 251
    }
167 252
}
253

  
254
void original::on_action_Nouvel_album_triggered()
255
{
256
    QTreeWidgetItem *i = new QTreeWidgetItem(ui->treeWidget);
257
    i->setText(0, trUtf8("Nouvel album"));
258
}
259

  
260
//---------------------------------------------------------------------------
261
void original::thumbUpdate(QModelIndex index)
262
{
263
    qDebug() << "original::thumbUpdate";
264
    ui->lvResult->update(m_modelView->mapFromSource(index));
265
}
266

  
267
void original::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
268
{
269
    QStringList items;
270
    m_modelList = new myModel();
271
    m_modelList->setRootPath("/tmp/");
272

  
273
    m_modelList->populateItem("/tmp/t/20120529-lea_plongee_cala_montjoi-000.jpg");
274
    m_modelList->populateItem("/tmp/t/20120529-lea_plongee_cala_montjoi-001.jpg");
275
    m_modelList->populateItem("/tmp/t/20120529-lea_plongee_cala_montjoi-002.jpg");
276
    m_modelList->populateItem("/tmp/t/20120529-lea_plongee_cala_montjoi-003.jpg");
277
    items.append("/tmp/t/20120529-lea_plongee_cala_montjoi-000.jpg");
278
    items.append("/tmp/t/20120529-lea_plongee_cala_montjoi-001.jpg");
279
    items.append("/tmp/t/20120529-lea_plongee_cala_montjoi-002.jpg");
280
    items.append("/tmp/t/20120529-lea_plongee_cala_montjoi-003.jpg");
281
    QtConcurrent::run(m_modelList,&myModel::loadThumbsQSL,items);
282

  
283
    m_modelView = new viewsSortProxyModel();
284
    m_modelView->setSourceModel(m_modelList);
285
    m_modelView->setSortCaseSensitivity(Qt::CaseInsensitive);
286
    ui->lvResult->setModel(m_modelView);
287

  
288
    connect(m_modelList,SIGNAL(thumbUpdate(QModelIndex)),this,SLOT(thumbUpdate(QModelIndex)));
289

  
290
}
original.h
29 29
#include <QMainWindow>
30 30
#include <exiv2/image.hpp>
31 31
#include <exiv2/exif.hpp>
32
#include "mymodelitem.h"
33
#include "mymodel.h"
32 34

  
33 35
namespace Ui {
34 36
class original;
......
44 46
    
45 47
private slots:
46 48
    void on_btnExport_clicked();
49
    void on_action_Nouvel_album_triggered();
50
    void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
51

  
52
public slots:
53
    void thumbUpdate(QModelIndex);
47 54

  
48 55
private:
49 56
    Ui::original *ui;
57
    myModel *m_modelList;
58
    QSortFilterProxyModel *m_modelView;
59

  
60
};
61

  
62

  
63
//---------------------------------------------------------------------------------
64
// Subclass QSortFilterProxyModel and override 'filterAcceptsRow' to only show
65
// directories in tree and not files.
66
//---------------------------------------------------------------------------------
67
class mainTreeFilterProxyModel : public QSortFilterProxyModel
68
{
69
protected:
70
    virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
71
};
72

  
73

  
74
//---------------------------------------------------------------------------------
75
// Subclass QSortFilterProxyModel and override 'lessThan' for sorting in list/details views
76
//---------------------------------------------------------------------------------
77
class viewsSortProxyModel : public QSortFilterProxyModel
78
{
79
protected:
80
    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
81
    bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
82
};
83

  
84

  
85
//---------------------------------------------------------------------------------
86
// Subclass QCompleter so we can use the SortFilterProxyModel above for the address bar.
87
//---------------------------------------------------------------------------------
88
class myCompleter : public QCompleter
89
{
90
public:
91
    QString pathFromIndex(const QModelIndex& index) const;
92
    QStringList splitPath(const QString& path) const;
50 93
};
51 94

  
52 95
#endif // ORIGINAL_H
original.pro
11 11

  
12 12

  
13 13
SOURCES += main.cpp\
14
        original.cpp
14
        original.cpp \
15
    mymodel.cpp \
16
    mymodelitem.cpp
15 17

  
16
HEADERS  += original.h
18
HEADERS  += original.h \
19
    mymodel.h \
20
    mymodelitem.h
17 21

  
18 22
FORMS    += original.ui
19 23

  
......
22 26

  
23 27
unix:LIBS += -lexiv2
24 28
win32:LIBS += -lexiv2
29

  
30
RESOURCES += \
31
    resources.qrc
original.ui
6 6
   <rect>
7 7
    <x>0</x>
8 8
    <y>0</y>
9
    <width>738</width>
10
    <height>300</height>
9
    <width>843</width>
10
    <height>457</height>
11 11
   </rect>
12 12
  </property>
13 13
  <property name="windowTitle">
14 14
   <string>original</string>
15 15
  </property>
16 16
  <widget class="QWidget" name="centralWidget">
17
   <widget class="QPushButton" name="btnExport">
18
    <property name="geometry">
19
     <rect>
20
      <x>70</x>
21
      <y>70</y>
22
      <width>92</width>
23
      <height>27</height>
24
     </rect>
25
    </property>
26
    <property name="text">
27
     <string>PushButton</string>
28
    </property>
29
   </widget>
30
   <widget class="QLineEdit" name="leDest">
31
    <property name="geometry">
32
     <rect>
33
      <x>70</x>
34
      <y>40</y>
35
      <width>113</width>
36
      <height>27</height>
37
     </rect>
38
    </property>
39
    <property name="text">
40
     <string>/tmp/w</string>
41
    </property>
42
   </widget>
43
   <widget class="QLineEdit" name="leSource">
44
    <property name="geometry">
45
     <rect>
46
      <x>70</x>
47
      <y>10</y>
48
      <width>113</width>
49
      <height>27</height>
50
     </rect>
51
    </property>
52
    <property name="text">
53
     <string>/tmp/t</string>
54
    </property>
55
   </widget>
17
   <layout class="QGridLayout" name="gridLayout">
18
    <item row="0" column="1">
19
     <widget class="QFrame" name="frame_2">
20
      <property name="sizePolicy">
21
       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
22
        <horstretch>0</horstretch>
23
        <verstretch>0</verstretch>
24
       </sizepolicy>
25
      </property>
26
      <property name="frameShape">
27
       <enum>QFrame::StyledPanel</enum>
28
      </property>
29
      <property name="frameShadow">
30
       <enum>QFrame::Raised</enum>
31
      </property>
32
      <layout class="QGridLayout" name="gridLayout_3">
33
       <item row="0" column="0">
34
        <widget class="QLineEdit" name="leSource">
35
         <property name="text">
36
          <string>/tmp/t</string>
37
         </property>
38
        </widget>
39
       </item>
40
       <item row="0" column="1">
41
        <widget class="QLineEdit" name="leDest">
42
         <property name="text">
43
          <string>/tmp/w</string>
44
         </property>
45
        </widget>
46
       </item>
47
       <item row="0" column="2">
48
        <widget class="QPushButton" name="btnExport">
49
         <property name="text">
50
          <string>PushButton</string>
51
         </property>
52
        </widget>
53
       </item>
54
       <item row="1" column="0" colspan="3">
55
        <widget class="QListView" name="lvResult">
56
         <property name="iconSize">
57
          <size>
58
           <width>96</width>
59
           <height>96</height>
60
          </size>
61
         </property>
62
         <property name="gridSize">
63
          <size>
64
           <width>128</width>
65
           <height>128</height>
66
          </size>
67
         </property>
68
         <property name="viewMode">
69
          <enum>QListView::IconMode</enum>
70
         </property>
71
         <property name="uniformItemSizes">
72
          <bool>true</bool>
73
         </property>
74
         <property name="wordWrap">
75
          <bool>true</bool>
76
         </property>
77
        </widget>
78
       </item>
79
      </layout>
80
     </widget>
81
    </item>
82
    <item row="0" column="0">
83
     <widget class="QTreeWidget" name="treeWidget">
84
      <property name="maximumSize">
85
       <size>
86
        <width>150</width>
87
        <height>16777215</height>
88
       </size>
89
      </property>
90
      <property name="editTriggers">
91
       <set>QAbstractItemView::AllEditTriggers</set>
92
      </property>
93
      <property name="alternatingRowColors">
94
       <bool>true</bool>
95
      </property>
96
      <attribute name="headerVisible">
97
       <bool>false</bool>
98
      </attribute>
99
      <column>
100
       <property name="text">
101
        <string notr="true">1</string>
102
       </property>
103
      </column>
104
     </widget>
105
    </item>
106
   </layout>
56 107
  </widget>
57 108
  <widget class="QMenuBar" name="menuBar">
58 109
   <property name="geometry">
59 110
    <rect>
60 111
     <x>0</x>
61 112
     <y>0</y>
62
     <width>738</width>
113
     <width>843</width>
63 114
     <height>25</height>
64 115
    </rect>
65 116
   </property>
117
   <widget class="QMenu" name="menu_Fichier">
118
    <property name="title">
119
     <string>&amp;Fichier</string>
120
    </property>
121
    <addaction name="action_Nouvel_album"/>
122
    <addaction name="separator"/>
123
    <addaction name="action_Quiter"/>
124
   </widget>
125
   <widget class="QMenu" name="menu_dition">
126
    <property name="title">
127
     <string>&amp;Édition</string>
128
    </property>
129
   </widget>
130
   <addaction name="menu_Fichier"/>
131
   <addaction name="menu_dition"/>
66 132
  </widget>
67 133
  <widget class="QToolBar" name="mainToolBar">
68 134
   <attribute name="toolBarArea">
......
73 139
   </attribute>
74 140
  </widget>
75 141
  <widget class="QStatusBar" name="statusBar"/>
142
  <action name="action_Quiter">
143
   <property name="text">
144
    <string>&amp;Quitter</string>
145
   </property>
146
   <property name="shortcut">
147
    <string>Ctrl+Q</string>
148
   </property>
149
  </action>
150
  <action name="action_Nouvel_album">
151
   <property name="text">
152
    <string>&amp;Nouvel album</string>
153
   </property>
154
   <property name="shortcut">
155
    <string>Ctrl+N</string>
156
   </property>
157
  </action>
76 158
 </widget>
77 159
 <layoutdefault spacing="6" margin="11"/>
78 160
 <resources/>
79
 <connections/>
161
 <connections>
162
  <connection>
163
   <sender>action_Quiter</sender>
164
   <signal>triggered()</signal>
165
   <receiver>original</receiver>
166
   <slot>close()</slot>
167
   <hints>
168
    <hint type="sourcelabel">
169
     <x>-1</x>
170
     <y>-1</y>
171
    </hint>
172
    <hint type="destinationlabel">
173
     <x>368</x>
174
     <y>149</y>
175
    </hint>
176
   </hints>
177
  </connection>
178
 </connections>
80 179
</ui>
resources.qrc
1
<RCC>
2
    <qresource prefix="/">
3
        <file>images/background.jpg</file>
4
    </qresource>
5
</RCC>

Formats disponibles : Unified diff

Redmine Appliance - Powered by TurnKey Linux