kdfwidget.cpp 15.3 KB
Newer Older
1
2
3
/*
 * kdfwidget.cpp
 *
Michael Kropfberger's avatar
Michael Kropfberger committed
4
 * Copyright (c) 1998-2001 Michael Kropfberger <michael.kropfberger@gmx.net>
5
 *               2009 Dario Andres Rodriguez <andresbajotierra@gmail.com>
6
7
8
9
10
11
12
13
14
15
16
17
18
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
Script Kiddy's avatar
Script Kiddy committed
19
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
 */
Laurent Montel's avatar
Laurent Montel committed
21

22
23
24
//
// 1999-11-29 Espen Sand
// Converted to QLayout and QListView + cleanups
25
26
// 1999-12-05 Espen Sand
// Usage bars should work again.
27
28
//

29
30
#include "kdfwidget.h"

31
#include "kdfprivate_debug.h"
32
#include "optiondialog.h"
Urs Wolfer's avatar
Urs Wolfer committed
33

34
35
36
37
#include <KMessageBox>
#include <KShell>
#include <KHelpClient>
#include <KConfigGroup>
38

39
40
41
42
43
44
45
#include <QAbstractEventDispatcher>
#include <QTimer>
#include <QLayout>
#include <QTreeView>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QPainter>
Yoann Laissus's avatar
Yoann Laissus committed
46
#include <QMenu>
47
#include <QProcess>
48

49
50
51
//This aren't used here...
//#define BAR_COLUMN   7
//#define FULL_PERCENT 95.0
52

53
#ifndef GUI_DEFINED
54
static bool GUI;
55
56
#define GUI_DEFINED
#endif
57

Dirk Mueller's avatar
Dirk Mueller committed
58
KDFWidget::KDFWidget( QWidget *parent, bool init )
Laurent Montel's avatar
Laurent Montel committed
59
        : QWidget(parent), mOptionDialog(nullptr), mPopup(nullptr), mTimer(nullptr)
60
{
Laurent Montel's avatar
Laurent Montel committed
61
62
63
64
65
66
67
68
69
70
71
72
73
    connect(&mDiskList , &DiskList::readDFDone,
            this, &KDFWidget::updateDFDone );
    connect(&mDiskList , &DiskList::criticallyFull,
            this, &KDFWidget::criticallyFull );

    m_columnList.append( Column( QStringLiteral( "Icon" ), QLatin1String( "" ), 20, IconCol ));
    m_columnList.append( Column( QStringLiteral( "Device" ), i18nc("Device of the storage", "Device"), 100, DeviceCol ));
    m_columnList.append( Column( QStringLiteral( "Type" ), i18nc("Filesystem on storage", "Type"), 80, TypeCol ));
    m_columnList.append( Column( QStringLiteral( "Size" ), i18nc("Total size of the storage", "Size"), 80, SizeCol ));
    m_columnList.append( Column( QStringLiteral( "MountPoint" ), i18nc("Mount point of storage", "Mount Point"), 120, MountPointCol ));
    m_columnList.append( Column( QStringLiteral( "Free" ), i18nc("Free space in storage", "Free"), 80, FreeCol ));
    m_columnList.append( Column( QStringLiteral( "Full%" ), i18nc("Used storage space in %", "Full %"), 50, FullCol ));
    m_columnList.append( Column( QStringLiteral( "UsageBar" ), i18nc("Usage graphical bar", "Usage"), 200, UsageBarCol ));
74
75
76
77
78
79

    GUI = !init;
    if( GUI )
    {
        QVBoxLayout *topLayout = new QVBoxLayout( this );
        topLayout->setSpacing( 0 );
Laurent Montel's avatar
Laurent Montel committed
80
        topLayout->setContentsMargins(0, 0, 0, 0);
81
82
83
84

        m_listModel = new QStandardItemModel( this );
        m_sortModel = new KDFSortFilterProxyModel( this );
        m_sortModel->setSourceModel( m_listModel );
85

86
87
88
89
        m_listWidget = new QTreeView( this );
        m_listWidget->setModel( m_sortModel );

        m_itemDelegate = new KDFItemDelegate( m_listWidget );
90

91
92
93
94
        m_listWidget->setItemDelegate( m_itemDelegate );
        m_listWidget->setRootIsDecorated( false );
        m_listWidget->setSortingEnabled( true );
        m_listWidget->setContextMenuPolicy( Qt::CustomContextMenu );
95
        m_listWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
96

97
98
        topLayout->addWidget( m_listWidget );

Laurent Montel's avatar
Laurent Montel committed
99
100
        connect( m_listWidget, &QWidget::customContextMenuRequested,
                 this, &KDFWidget::contextMenuRequested);
101
102
103

        makeColumns();

104
        mIsTopLevel = QLatin1String(parent->metaObject()->className()) == QLatin1String( "KDFTopLevel" ) ? true : false;
105
    }
106

107
108
109
110
    loadSettings();
    if( init )
        applySettings();
}
111

Laurent Montel's avatar
Laurent Montel committed
112
KDFWidget::~KDFWidget()
113
{
114
115
116
117
    delete m_listModel;
    delete m_sortModel;
    delete m_itemDelegate;
    delete m_listWidget;
Laurent Montel's avatar
Laurent Montel committed
118
}
119

120
121
122
void KDFWidget::makeColumns( void )
{

123
    QStringList columns;
124
    for (const Column &c : qAsConst(m_columnList)){
125
126
127
        columns << c.columnName;
    }
    m_listModel->setHorizontalHeaderLabels( columns );
128

129
}
130

Michael Kropfberger's avatar
Michael Kropfberger committed
131
/******************************************************************/
132
133
void KDFWidget::closeEvent(QCloseEvent *)
{
134
    applySettings();
135
    qApp->quit();
Dirk Mueller's avatar
Dirk Mueller committed
136
}
137
138


139
140
void KDFWidget::settingsChanged( void )
{
141
142
    applySettings();
    loadSettings();
143
144
145
}


Michael Kropfberger's avatar
Michael Kropfberger committed
146
147
148
/***************************************************************************
  * writes the KConfig
**/
149
void KDFWidget::applySettings( void )
150
{
151
152
    KConfig m_config;
    KConfigGroup config( &m_config, "KDiskFree" );
153

154
    if( GUI )
155
    {
156
        for (const Column &c : qAsConst(m_columnList)){
157
158
159
            if( !m_listWidget->isColumnHidden( c.number ) )
                config.writeEntry( c.name, m_listWidget->columnWidth(c.number) );
        }
160
161
162
163
164
165
166
167
168
169
170

        config.writeEntry("SortColumn", m_sortModel->sortColumn());
        config.writeEntry("SortOrder", (int)m_sortModel->sortOrder());

        //Save the sort order of the QTreeView Header
        QHeaderView * header = m_listWidget->header();
        QList<int> sectionIndices;
        for (int i = 0; i < header->count(); i++) {
            sectionIndices.append(header->visualIndex(i));
        }
        config.writeEntry("HeaderSectionIndices", sectionIndices);
171
    }
172
173
    config.sync();
    updateDF();
174
175
}

176

177
178
179
/***************************************************************************
  * reads the KConfig
**/
180
void KDFWidget::loadSettings( void )
181
{
182
    mStd.updateConfiguration();
183

184
    if(GUI)
185
    {
186
        KConfigGroup config(KSharedConfig::openConfig(), "KDiskFree");
187
        for (const Column &c : qAsConst(m_columnList)){
188
189
190
191
            int width = config.readEntry( c.name, c.defaultWidth );
            m_listWidget->setColumnWidth( c.number, width );
        }

192
        KConfigGroup config_visible(KSharedConfig::openConfig(), "KDFConfig");
193
        for (const Column &c : qAsConst(m_columnList)){
194
195
196
197
            bool visible = config_visible.readEntry( c.name , true );
            m_listWidget->setColumnHidden( c.number, !visible );
        }

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
        int sortColumn = config.readEntry("SortColumn",0);
        int sortOrder = config.readEntry("SortOrder",(int)Qt::AscendingOrder);
        m_listWidget->sortByColumn(sortColumn,Qt::SortOrder(sortOrder));

        //Load the sort order of the QTreeView Header
        //This can also be achieved by header->saveState() and header->restoreState(...),
        //but this would not be "human-readable" any more...
        QHeaderView * header = m_listWidget->header();
        QList<int> sectionIndices;
        sectionIndices = config.readEntry("HeaderSectionIndices",sectionIndices);
        if (sectionIndices.count() == header->count()) {
            for (int i = 0; i < header->count(); i++) {
                int sectionIndex = sectionIndices.at(i);
                int oldVisualIndex = header->visualIndex(sectionIndex);
                header->moveSection(oldVisualIndex,i);
            }
        }

216
217
        setUpdateFrequency( mStd.updateFrequency() );
        updateDF();
218
    }
219
220
}

221

222
223
224
/***************************************************************************
  * pops up the SettingsBox if the settingsBtn is clicked
**/
225
void KDFWidget::settingsBtnClicked( void )
226
{
227
    if( mIsTopLevel == true )
228
    {
Laurent Montel's avatar
Laurent Montel committed
229
        if( mOptionDialog == nullptr )
230
231
        {
            mOptionDialog = new COptionDialog( this );
Laurent Montel's avatar
Laurent Montel committed
232
            if( mOptionDialog == nullptr )
233
234
235
            {
                return;
            }
Laurent Montel's avatar
Laurent Montel committed
236
237
            connect( mOptionDialog, &COptionDialog::valueChanged,
                     this, &KDFWidget::settingsChanged );
238
239
        }
        mOptionDialog->show();
240
    }
241
242
243
244
245
246
}


/***************************************************************************
  * resets the timer for automatic df-refreshes
**/
247
void KDFWidget::setUpdateFrequency( int frequency )
248
{
249
250
251
252
253
254
255
256
257
    //
    // Kill current timer and restart it if the frequency is
    // larger than zero.
    //
    QAbstractEventDispatcher::instance()->unregisterTimers(this);
    if( frequency > 0 )
    {
        startTimer( frequency * 1000 );
    }
258
259
260
261
262
}

/***************************************************************************
  * Update (reread) all disk-dependencies
**/
Laurent Montel's avatar
Laurent Montel committed
263
void KDFWidget::timerEvent(QTimerEvent *)
264
{
265
    updateDF();
266
267
}

268
269

/***************************************************************************
Laurent Montel's avatar
Laurent Montel committed
270
  * checks fstab & df
271
**/
272
void KDFWidget::updateDF( void )
273
{
274
275
276
    //
    // We can only do this if the popupmenu is not present
    //
Laurent Montel's avatar
Laurent Montel committed
277
    if( mPopup == nullptr )
278
279
280
281
282
    {
        readingDF = true;
        mDiskList.readFSTAB();
        mDiskList.readDF();
    }
Espen Sand's avatar
Espen Sand committed
283
}
284
285
286
287

/***************************************************************************
  * gets the signal when the diskList is complete and up to date
**/
288
void KDFWidget::updateDFDone( void ){
289
290
291
292
293
294
295
296
297
    if (mPopup) //The popup menu is ont he screen... Don't touch the list view...
        return;

    //Clear the list items
    m_listModel->removeRows(0,m_listModel->rowCount());

    DisksConstIterator itr = mDiskList.disksConstIteratorBegin();
    DisksConstIterator end = mDiskList.disksConstIteratorEnd();
    for (; itr != end; ++itr)
298
    {
299
        DiskEntry * disk = *itr;
300

301
302
303
        QString size,percent;
        if( disk->kBSize() > 0 )
        {
304
            percent = i18nc("Disk percentage", "%1%", QString::number(disk->percentFull()));
305
306
307
308
309
310
311
312
            size = disk->prettyKBSize();
        }
        else
        {
            percent = i18n("N/A");
            size = i18n("N/A");
        }

313
        bool root = !disk->mountOptions().contains(QLatin1String( "user" ), Qt::CaseInsensitive);
314

315
        QStandardItem * IconItem = new QStandardItem( generateIcon(disk->iconName(), root, disk->mounted() ), QLatin1String( "" ) );
316
317
318
319

        QStandardItem * DeviceItem = new QStandardItem( disk->deviceName() );

        QStandardItem * TypeItem = new QStandardItem( disk->fsType() );
320

321
322
        QStandardItem * SizeItem = new QStandardItem( size );
        SizeItem->setData( disk->kBSize(), Qt::UserRole );
323

324
        QStandardItem * MountPointItem = new QStandardItem( disk->mountPoint() );
325

326
327
        QStandardItem * FreeItem = new QStandardItem( disk->prettyKBAvail() );
        FreeItem->setData( disk->kBAvail(), Qt::UserRole );
328

329
330
        QStandardItem * FullItem = new QStandardItem( percent );
        FullItem->setData( disk->percentFull() , Qt::UserRole );
331

332
        QStandardItem * UsageBarItem = new QStandardItem( QLatin1String( "" ) );
333
        UsageBarItem->setData( disk->percentFull(), Qt::UserRole );
334

335
336
        m_listModel->appendRow( QList<QStandardItem*>() << IconItem <<  DeviceItem << TypeItem << SizeItem << MountPointItem <<
          FreeItem << FullItem << UsageBarItem);
337
    }
338

339
    readingDF = false;
340

341
    m_listModel->sort( DeviceCol );
342

Espen Sand's avatar
Espen Sand committed
343
}
344

Laurent Montel's avatar
Laurent Montel committed
345
QIcon KDFWidget::generateIcon( const QString &iconName, bool mode, bool mounted)
346
{
347
    QPixmap pix = SmallIcon(iconName);
348

349
    QPainter painter(&pix);
350

351
    if( mode )
Laurent Montel's avatar
Laurent Montel committed
352
        painter.drawPixmap( QRect(0,6,10,10), SmallIcon(QStringLiteral( "object-locked" )) );
Laurent Montel's avatar
Laurent Montel committed
353

354
    if( mounted )
Laurent Montel's avatar
Laurent Montel committed
355
        painter.drawPixmap( QRect(6,6,12,12) , SmallIcon(QStringLiteral( "emblem-mounted" )) );
356

357
358
    painter.end();
    return QIcon(pix);
359

360
361
362
}

void KDFWidget::criticallyFull( DiskEntry *disk )
363
{
364
    if( mStd.popupIfFull() == true )
Michael Kropfberger's avatar
Michael Kropfberger committed
365
    {
366
367
368
        QString msg = i18n("Device [%1] on [%2] is critically full.",
                           disk->deviceName(), disk->mountPoint());
        KMessageBox::sorry( this, msg, i18nc("Warning device getting critically full", "Warning"));
Michael Kropfberger's avatar
Michael Kropfberger committed
369
    }
370
}
371

Laurent Montel's avatar
Laurent Montel committed
372
DiskEntry * KDFWidget::selectedDisk( const QModelIndex &index )
373
{
374
    if( !index.isValid() )
Laurent Montel's avatar
Laurent Montel committed
375
        return nullptr;
376

377
378
    QStandardItem * itemDevice = m_listModel->item( index.row() , DeviceCol );
    QStandardItem * itemMountPoint = m_listModel->item( index.row() , MountPointCol );
379

380
381
    DiskEntry * disk = new DiskEntry( itemDevice->text() );
    disk->setMountPoint( itemMountPoint->text() );
382

383
    int pos = mDiskList.find( disk );
384

385
386
    delete disk;
    return mDiskList.at(pos);
387

388
}
389

390
void KDFWidget::contextMenuRequested( const QPoint &p )
391
{
392
393
    if (mPopup) //The user may even be able to popup another menu while this open is active...
        return;
394

395
    QModelIndex index = m_listWidget->indexAt( p );
396

397
398
399
400
401
402
403
404
    if( !index.isValid() )
    {
        QList<QModelIndex> selected = m_listWidget->selectionModel()->selectedIndexes();
        if ( selected.size() > 0 )
            index = selected.at(0);
        else
            return;
    }
405

406
    index = m_sortModel->mapToSource( index );
407

408
    mDiskList.setUpdatesDisabled(true);
409
    DiskEntry * disk = selectedDisk( index );
410

Laurent Montel's avatar
Laurent Montel committed
411
    if( disk == nullptr )
412
413
        return;

Laurent Montel's avatar
Laurent Montel committed
414
    mPopup = new QMenu( nullptr );
Yoann Laissus's avatar
Yoann Laissus committed
415
    mPopup->setTitle( disk->mountPoint() );
416
417
418
419
420
421
422
423
424
425
426
    QAction *mountPointAction = mPopup->addAction( i18n("Mount Device") );
    QAction *umountPointAction = mPopup->addAction( i18n("Unmount Device") );
    mPopup->addSeparator();
    QAction *openFileManagerAction = mPopup->addAction( i18n("Open in File Manager") );
    mountPointAction->setEnabled( !disk->mounted() );
    umountPointAction->setEnabled( disk->mounted() );
    openFileManagerAction->setEnabled( disk->mounted() );
    QAction *position = mPopup->exec( m_listWidget->mapToGlobal(p) );

    bool openFileManager = false;
    if( !position )
427
    {
428
429
        mDiskList.setUpdatesDisabled(false);
        delete mPopup;
Laurent Montel's avatar
Laurent Montel committed
430
        mPopup = nullptr;
431
432
433
434
435
436
        return;
    }
    else if( position == mountPointAction || position == umountPointAction )
    {
        QStandardItem * SizeItem = m_listModel->item( index.row() , SizeCol );
        SizeItem->setText( i18n("MOUNTING") );
437

438
439
        QStandardItem * FreeItem = m_listModel->item( index.row() , FreeCol );
        FreeItem->setText( i18n("MOUNTING") );
440

441
        QStandardItem * IconItem = m_listModel->item( index.row() , IconCol );
442
        IconItem->setIcon( SmallIcon(QLatin1String( "user-away" )) );
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460

        int val = disk->toggleMount();
        if( val != 0 /*== false*/ )
        {
            KMessageBox::error( this, disk->lastSysError() );
        }
        else if ( ( mStd.openFileManager() == true)
                  && (position == mountPointAction) ) //only on mount
        {
            openFileManager = true;
        }

        //delete item;
        mDiskList.deleteAllMountedAt(disk->mountPoint());
    }
    else if( position == openFileManagerAction )
    {
        openFileManager = true;
461
    }
462

463
464
    if( openFileManager == true )
    {
465
        qCDebug(KDF) << "opening filemanager";
466
467
468
        if(  mStd.fileManager().isEmpty() == false )
        {
            QString cmd = mStd.fileManager();
469
            int pos = cmd.indexOf(QLatin1String( "%m" ));
470
471
            if( pos > 0 )
            {
472
                cmd.replace(pos, 2, KShell::quoteArg(disk->mountPoint()));
473
474
475
            }
            else
            {
476
                cmd += QLatin1Char( ' ' ) + KShell::quoteArg(disk->mountPoint());
477
            }
478
            QProcess::startDetached(cmd, QStringList());
479
480
        }
    }
481

482
483
484
    //Update only here as showing of error message triggers event loop.
    mDiskList.setUpdatesDisabled(false);
    delete mPopup;
Laurent Montel's avatar
Laurent Montel committed
485
    mPopup = nullptr;
486

487
488
489
490
    if( position != openFileManagerAction ) // No need to update when just opening the fm.
    {
        updateDF();
    }
Laurent Montel's avatar
Laurent Montel committed
491

492
493
}

Stephan Kulow's avatar
Stephan Kulow committed
494
void KDFWidget::invokeHelp()
Alex Zepeda's avatar
Alex Zepeda committed
495
{
Laurent Montel's avatar
Laurent Montel committed
496
    KHelpClient::invokeHelp(QLatin1String( "" ), QStringLiteral( "kcontrol/kdf" ));
Alex Zepeda's avatar
Alex Zepeda committed
497
498
}