Projet

Général

Profil

Révision 92dc01fa

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
25 25
#include "ui_original.h"
26 26

  
27 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 28
//---------------------------------------------------------------------------
92 29
QString formatSize(qint64 num)
93 30
{
......
114 51
    ui(new Ui::original)
115 52
{
116 53
    ui->setupUi(this);
54

  
55
    ui->stackedWidget->setCurrentWidget(ui->page);
56

  
57
    QDir dir(QDir::homePath() + "/RyXeo-WebPhotoAlbum");
58
    dir.setFilter(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
59
    QFileInfoList list = dir.entryInfoList();
60
    for(int i = 0; i < list.count(); i++) {
61
        QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
62
        item->setText(0, list.at(i).fileName());
63
        item->setData(1,0,list.at(i).absoluteFilePath());
64
    }
117 65
}
118 66

  
119 67
original::~original()
......
190 138
                {
191 139
                    qDebug() << i->key().c_str() << " = " << i->value().toString().c_str();
192 140
                    if (i->key() == "Exif.Image.Artist") {
193
                        exifData["Exif.Image.Artist"]    = "Toto le hero";
141
                        exifData["Exif.Image.Artist"]    = "Eric S.";
194 142
                        setArtist = true;
195 143
                    }
196 144
                    if (i->key() == "Exif.Image.Copyright") {
197
                        exifData["Exif.Image.Copyright"]    = "Toto le hero";
145
                        exifData["Exif.Image.Copyright"]    = "Eric S.";
198 146
                        setCopyright = true;
199 147
                    }
200 148
                    if (i->key() == "Exif.Image.Software") {
......
208 156
                if(!setArtist) {
209 157
                    Exiv2::ExifKey k("Exif.Image.Artist");
210 158
                    Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::asciiString);
211
                    v->read("Toto le hero");
159
                    v->read("Eric S.");
212 160
                    exifData.add(k,v.get());
213 161
                }
214 162

  
215 163
                if(!setCopyright) {
216 164
                    Exiv2::ExifKey k2("Exif.Image.Copyright");
217 165
                    Exiv2::Value::AutoPtr v2 = Exiv2::Value::create(Exiv2::asciiString);
218
                    v2->read("Toto le hero");
166
                    v2->read("Eric S.");
219 167
                    exifData.add(k2,v2.get());
220 168
                }
221 169

  
......
257 205
    i->setText(0, trUtf8("Nouvel album"));
258 206
}
259 207

  
260
//---------------------------------------------------------------------------
261
void original::thumbUpdate(QModelIndex index)
208
void original::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
262 209
{
263
    qDebug() << "original::thumbUpdate";
264
    ui->lvResult->update(m_modelView->mapFromSource(index));
210
    ui->lwPictures->clear();
211
    QDir dir(item->data(1,0).toString()+"/thumbs/");
212
    dir.setFilter(QDir::Files);
213
    dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
214
    QFileInfoList list = dir.entryInfoList();
215
    for(int i = 0; i < list.count(); i++) {
216
        qDebug() << list.at(i).fileName();
217
        QListWidgetItem *newitem = new QListWidgetItem();
218
        QIcon icone(list.at(i).absoluteFilePath());//pour la mettre  à coté de l'item
219
        newitem->setIcon(icone); // ajout de la petite icone sur l'item
220
        newitem->setText(list.at(i).fileName());
221
        ui->lwPictures->insertItem(i,newitem);
222
    }
265 223
}
266 224

  
267
void original::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
225
void original::on_commandLinkButton_clicked()
226
{
227
    if(ui->stackedWidget->currentWidget() == ui->page_2)
228
        ui->stackedWidget->setCurrentWidget(ui->page);
229
    else {
230
        QFileInfo fi(ui->treeWidget->currentItem()->data(1,0).toString()+"/info.txt");
231
        qDebug() << "Lecture de " << fi.absoluteFilePath();
232
        if(fi.exists()) {
233
            QFile file(fi.absoluteFilePath());
234
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
235
                return;
236

  
237
            /* Exemple de fichier
238
            name|Sortie Plongée SAGC. (Cala Montjoi, Spain) 28.05.2012
239
            author|Éric Seigne
240
            description|Sortie Plongée SAGC. (Cala Montjoi, Spain)
241
            date|28.05.2012
242
            restricted_user|sagc
243
            restricted_password|motdepasse
244
              */
245
            while (!file.atEnd()) {
246
                QByteArray line = file.readLine();
247
                QStringList tab = QString::fromUtf8(line.constData()).split('|');
248
                if(tab.at(0) == "name")
249
                    ui->leTitre->setText(tab.at(1));
250
                if(tab.at(0) == "author")
251
                    ui->leAuthor->setText(tab.at(1));
252
                if(tab.at(0) == "description")
253
                    ui->leDesc->setText(tab.at(1));
254
                if(tab.at(0) == "date")
255
                    ui->dateEdit->setDate(QDate::fromString(tab.at(1)));
256
                if(tab.at(0) == "restricted_user")
257
                    ui->leLogin->setText(tab.at(1));
258
                if(tab.at(0) == "restricted_password")
259
                    ui->lePasswd->setText(tab.at(1));
260

  
261
            }
262

  
263
        }
264
        ui->stackedWidget->setCurrentWidget(ui->page_2);
265
    }
266
}
267

  
268
void original::on_btnSave_clicked()
268 269
{
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 270

  
290 271
}
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
#include <QTreeWidgetItem>
33
#include <QListWidgetItem>
34 34

  
35 35
namespace Ui {
36 36
class original;
......
48 48
    void on_btnExport_clicked();
49 49
    void on_action_Nouvel_album_triggered();
50 50
    void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
51

  
52
public slots:
53
    void thumbUpdate(QModelIndex);
51
    void on_commandLinkButton_clicked();
52
    void on_btnSave_clicked();
54 53

  
55 54
private:
56 55
    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;
93 56
};
94 57

  
95 58
#endif // ORIGINAL_H
original.pro
9 9
TARGET = original
10 10
TEMPLATE = app
11 11

  
12

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

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

  
22 17
FORMS    += original.ui
23 18

  
24
# include("lib/openexif/openexif.pri")
25
# include("lib/exiv2/exiv2.pri")
26

  
27 19
unix:LIBS += -lexiv2
28 20
win32:LIBS += -lexiv2
29 21

  
30
RESOURCES += \
31
    resources.qrc
22
RESOURCES += resources.qrc
original.ui
16 16
  <widget class="QWidget" name="centralWidget">
17 17
   <layout class="QGridLayout" name="gridLayout">
18 18
    <item row="0" column="1">
19
     <widget class="QFrame" name="frame_2">
19
     <widget class="QFrame" name="frmPrincipale">
20 20
      <property name="sizePolicy">
21 21
       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
22 22
        <horstretch>0</horstretch>
......
51 51
         </property>
52 52
        </widget>
53 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>
54
       <item row="0" column="3">
55
        <widget class="QCommandLinkButton" name="commandLinkButton">
56
         <property name="text">
57
          <string>Propriétés</string>
70 58
         </property>
71
         <property name="uniformItemSizes">
72
          <bool>true</bool>
59
        </widget>
60
       </item>
61
       <item row="1" column="0" colspan="4">
62
        <widget class="QStackedWidget" name="stackedWidget">
63
         <property name="currentIndex">
64
          <number>1</number>
73 65
         </property>
74
         <property name="wordWrap">
75
          <bool>true</bool>
66
         <widget class="QWidget" name="page">
67
          <layout class="QGridLayout" name="gridLayout_4">
68
           <item row="0" column="0">
69
            <widget class="QListWidget" name="lwPictures">
70
             <property name="iconSize">
71
              <size>
72
               <width>120</width>
73
               <height>120</height>
74
              </size>
75
             </property>
76
             <property name="gridSize">
77
              <size>
78
               <width>128</width>
79
               <height>128</height>
80
              </size>
81
             </property>
82
             <property name="viewMode">
83
              <enum>QListView::IconMode</enum>
84
             </property>
85
            </widget>
86
           </item>
87
          </layout>
88
         </widget>
89
         <widget class="QWidget" name="page_2">
90
          <layout class="QGridLayout" name="gridLayout_2">
91
           <item row="0" column="0">
92
            <widget class="QLabel" name="label_5">
93
             <property name="text">
94
              <string>Titre</string>
95
             </property>
96
            </widget>
97
           </item>
98
           <item row="0" column="1">
99
            <widget class="QLineEdit" name="leTitre"/>
100
           </item>
101
           <item row="1" column="0">
102
            <widget class="QLabel" name="label_3">
103
             <property name="text">
104
              <string>Description</string>
105
             </property>
106
            </widget>
107
           </item>
108
           <item row="1" column="1">
109
            <widget class="QLineEdit" name="leDesc"/>
110
           </item>
111
           <item row="2" column="0">
112
            <widget class="QLabel" name="label_6">
113
             <property name="text">
114
              <string>Auteur</string>
115
             </property>
116
            </widget>
117
           </item>
118
           <item row="2" column="1">
119
            <widget class="QLineEdit" name="leAuthor"/>
120
           </item>
121
           <item row="2" column="2">
122
            <widget class="QLabel" name="label">
123
             <property name="text">
124
              <string>Date</string>
125
             </property>
126
            </widget>
127
           </item>
128
           <item row="2" column="3">
129
            <widget class="QDateEdit" name="dateEdit">
130
             <property name="calendarPopup">
131
              <bool>true</bool>
132
             </property>
133
            </widget>
134
           </item>
135
           <item row="3" column="0" colspan="4">
136
            <widget class="QGroupBox" name="groupBox">
137
             <property name="title">
138
              <string>Album photo protégé par mot de passe </string>
139
             </property>
140
             <layout class="QFormLayout" name="formLayout">
141
              <item row="1" column="0">
142
               <widget class="QLabel" name="label_4">
143
                <property name="text">
144
                 <string>Identifiant</string>
145
                </property>
146
               </widget>
147
              </item>
148
              <item row="1" column="1">
149
               <widget class="QLineEdit" name="leLogin"/>
150
              </item>
151
              <item row="2" column="0">
152
               <widget class="QLabel" name="label_2">
153
                <property name="text">
154
                 <string>Mot de passe</string>
155
                </property>
156
               </widget>
157
              </item>
158
              <item row="2" column="1">
159
               <widget class="QLineEdit" name="lePasswd"/>
160
              </item>
161
              <item row="0" column="0" colspan="2">
162
               <widget class="QLabel" name="label_7">
163
                <property name="text">
164
                 <string>Complétez les deux champs ci-dessous si vous voulez protéger l'accès (lorsqu'il sera publié sur internet) à cet album photo par un identifiant et un mot de passe.</string>
165
                </property>
166
                <property name="wordWrap">
167
                 <bool>true</bool>
168
                </property>
169
               </widget>
170
              </item>
171
             </layout>
172
            </widget>
173
           </item>
174
          </layout>
175
         </widget>
176
        </widget>
177
       </item>
178
       <item row="2" column="3">
... Ce différentiel a été tronqué car il excède la taille maximale pouvant être affichée.

Formats disponibles : Unified diff

Redmine Appliance - Powered by TurnKey Linux