File indexing completed on 2024-04-14 15:49:46

0001 // SPDX-License-Identifier: GPL-3.0-or-later
0002 /*
0003   Copyright 2017 - 2020 Martin Koller, kollix@aon.at
0004 
0005   This file is part of liquidshell.
0006 
0007   liquidshell is free software: you can redistribute it and/or modify
0008   it under the terms of the GNU General Public License as published by
0009   the Free Software Foundation, either version 3 of the License, or
0010   (at your option) any later version.
0011 
0012   liquidshell is distributed in the hope that it will be useful,
0013   but WITHOUT ANY WARRANTY; without even the implied warranty of
0014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0015   GNU General Public License for more details.
0016 
0017   You should have received a copy of the GNU General Public License
0018   along with liquidshell.  If not, see <http://www.gnu.org/licenses/>.
0019 */
0020 
0021 #include <DiskUsageApplet.hxx>
0022 
0023 #include <QLabel>
0024 #include <QProgressBar>
0025 #include <QGridLayout>
0026 #include <QAction>
0027 #include <QFileInfo>
0028 #include <QStorageInfo>
0029 #include <QDebug>
0030 
0031 #include <Solid/Device>
0032 #include <Solid/DeviceNotifier>
0033 #include <Solid/StorageVolume>
0034 #include <Solid/StorageAccess>
0035 #include <KLocalizedString>
0036 #include <KConfig>
0037 #include <KConfigGroup>
0038 #include <KIO/Global>
0039 
0040 #include <cmath>
0041 
0042 //--------------------------------------------------------------------------------
0043 
0044 DiskUsageApplet::DiskUsageApplet(QWidget *parent, const QString &theId)
0045   : DesktopApplet(parent, theId)
0046 {
0047   setAutoFillBackground(true);
0048 
0049   connect(&timer, &QTimer::timeout, this, &DiskUsageApplet::fill);
0050   timer.setInterval(10000);
0051   timer.start();
0052 
0053   new QGridLayout(this);
0054   fill();
0055 
0056   // beside cyclic update, react immediately when a device is added/removed
0057   connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded,
0058           this, &DiskUsageApplet::fill);
0059 
0060   connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved,
0061           this, &DiskUsageApplet::fill);
0062 }
0063 
0064 //--------------------------------------------------------------------------------
0065 
0066 void DiskUsageApplet::fill()
0067 {
0068   QGridLayout *grid = static_cast<QGridLayout *>(layout());
0069 
0070   for (SizeInfo &info : partitionMap)
0071     info.used = false;
0072 
0073   QList<Solid::Device> partitions = Solid::Device::listFromType(Solid::DeviceInterface::StorageVolume);
0074 
0075   int row = grid->rowCount();
0076   for (const Solid::Device &partition : partitions)
0077   {
0078     const Solid::StorageVolume *volume = partition.as<Solid::StorageVolume>();
0079     if ( !volume || volume->isIgnored() ||
0080          (volume->usage() != Solid::StorageVolume::FileSystem) )
0081       continue;
0082 
0083     const Solid::StorageAccess *storage = partition.as<Solid::StorageAccess>();
0084     if ( !storage )
0085       continue;
0086 
0087     if ( !storage->isAccessible() )
0088     {
0089       connect(storage, &Solid::StorageAccess::setupDone, this, &DiskUsageApplet::fill, Qt::UniqueConnection);
0090       continue;
0091     }
0092 
0093     QProgressBar *progress;
0094     QLabel *sizeLabel;
0095 
0096     QStorageInfo info = QStorageInfo(storage->filePath());
0097 
0098     //qDebug() << "mount" << info.rootPath() << "path" << storage->filePath()
0099     //         << "valid" << info.isValid() << "bytesTotal" << info.bytesTotal()
0100     //         << "available" << info.bytesAvailable() << "free" << info.bytesFree()
0101     //         << "readable" << QFileInfo(storage->filePath()).isReadable();
0102 
0103     if ( !info.isValid() || (info.bytesTotal() == 0) || !info.isReady() || !QFileInfo(storage->filePath()).isReadable() )
0104       continue;
0105 
0106     QString key = storage->filePath();
0107 
0108     if ( !partitionMap.contains(key) )
0109     {
0110       progress = new QProgressBar(this);
0111 
0112       QLabel *label = new QLabel(storage->filePath(), this);
0113       grid->addWidget(label, row, 0);
0114       grid->addWidget(progress, row, 1);
0115       grid->addWidget(sizeLabel = new QLabel(this), row, 2);
0116 
0117       row++;
0118 
0119       SizeInfo sizeInfo;
0120       sizeInfo.label = label;
0121       sizeInfo.progress = progress;
0122       sizeInfo.sizeLabel = sizeLabel;
0123       sizeInfo.used = true;
0124       partitionMap.insert(key, sizeInfo);
0125 
0126       // workaround Qt bug
0127       label->setPalette(palette());
0128       sizeLabel->setPalette(palette());
0129       progress->setPalette(palette());
0130 
0131       connect(storage, &Solid::StorageAccess::teardownDone, this, &DiskUsageApplet::fill, Qt::UniqueConnection);
0132     }
0133     else
0134     {
0135       partitionMap[key].used = true;
0136       SizeInfo sizeInfo = partitionMap[key];
0137       progress = sizeInfo.progress;
0138       sizeLabel = sizeInfo.sizeLabel;
0139     }
0140 
0141     progress->setValue(std::round(double(info.bytesTotal() - info.bytesAvailable()) / double(info.bytesTotal()) * 100.0));
0142 
0143     sizeLabel->setText(i18n("%1 free / %2",
0144                             KIO::convertSize(info.bytesAvailable()),
0145                             KIO::convertSize(info.bytesTotal())));
0146   }
0147 
0148   // remove entries which are no longer used
0149   QMutableMapIterator<QString, SizeInfo> iter(partitionMap);
0150   while ( iter.hasNext() )
0151   {
0152     iter.next();
0153     if ( !iter.value().used )
0154     {
0155       delete iter.value().label;
0156       delete iter.value().progress;
0157       delete iter.value().sizeLabel;
0158 
0159       iter.remove();
0160     }
0161   }
0162 }
0163 
0164 //--------------------------------------------------------------------------------
0165 
0166 void DiskUsageApplet::configure()
0167 {
0168   if ( dialog )
0169   {
0170     dialog->raise();
0171     dialog->activateWindow();
0172     return;
0173   }
0174 
0175   dialog = new DiskUsageAppletConfigureDialog(this);
0176   dialog->setWindowTitle(i18n("Configure DiskUsage Applet"));
0177 
0178   dialog->setAttribute(Qt::WA_DeleteOnClose);
0179   dialog->show();
0180 
0181   connect(dialog.data(), &QDialog::accepted, this, &DiskUsageApplet::saveConfig);
0182 }
0183 
0184 //--------------------------------------------------------------------------------
0185 
0186 void DiskUsageApplet::loadConfig()
0187 {
0188   DesktopApplet::loadConfig();
0189 
0190   KConfig config;
0191   KConfigGroup group = config.group(id);
0192 
0193   QColor barTextCol = group.readEntry("barTextCol", palette().color(QPalette::HighlightedText));
0194   QColor barBackCol = group.readEntry("barBackCol", palette().color(QPalette::Highlight));
0195 
0196   QPalette pal = palette();
0197   pal.setColor(QPalette::HighlightedText, barTextCol);
0198   pal.setColor(QPalette::Highlight, barBackCol);
0199   setPalette(pal);
0200 }
0201 
0202 //--------------------------------------------------------------------------------
0203 
0204 void DiskUsageApplet::saveConfig()
0205 {
0206   DesktopApplet::saveConfig();
0207 
0208   KConfig config;
0209   KConfigGroup group = config.group(id);
0210   group.writeEntry("barTextCol", palette().color(QPalette::HighlightedText));
0211   group.writeEntry("barBackCol", palette().color(QPalette::Highlight));
0212 }
0213 
0214 //--------------------------------------------------------------------------------