File indexing completed on 2024-11-10 05:13:56
0001 /* 0002 SPDX-FileCopyrightText: 1999 Michael Kropfberger <michael.kropfberger@gmx.net> 0003 SPDX-FileCopyrightText: 2009 Dario Andres Rodriguez <andresbajotierra@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 // 0009 // 1999-12-03 Espen Sand 0010 // Cleanups, improvements and fixes for KDE-2 0011 // 0012 // 2004-07-15 Stanislav Karchebny 0013 // Rewrite for KDE 3 0014 // 0015 0016 #include "kwikdisk.h" 0017 0018 #include "kdf_version.h" 0019 #include "kwikdisk_debug.h" 0020 0021 #include <KAboutData> 0022 #include <KDialogJobUiDelegate> 0023 #include <KHelpClient> 0024 #include <KMessageBox> 0025 #include <KIO/CommandLauncherJob> 0026 #include <KShell> 0027 #include <KLocalizedString> 0028 0029 #include <QApplication> 0030 #include <QCommandLineParser> 0031 #include <QAbstractEventDispatcher> 0032 #include <QPainter> 0033 #include <QPixmap> 0034 #include <QActionGroup> 0035 #include <QMenu> 0036 #include <QProcess> 0037 0038 #include <unistd.h> 0039 0040 /*****************************************************************************/ 0041 0042 KwikDisk::KwikDisk() 0043 : KStatusNotifierItem() 0044 , m_readingDF(false) 0045 , m_dirty(true) 0046 , m_inside(false) 0047 , m_optionDialog(nullptr) 0048 { 0049 qCDebug(KDF); 0050 0051 setIconByName(QStringLiteral("kdf")); 0052 0053 connect( &m_diskList, &DiskList::readDFDone, this, &KwikDisk::updateDFDone ); 0054 connect( &m_diskList, &DiskList::criticallyFull, 0055 this, &KwikDisk::criticallyFull ); 0056 0057 m_actionGroup = new QActionGroup( this ); 0058 connect( m_actionGroup, &QActionGroup::triggered , this, &KwikDisk::toggleMount ); 0059 0060 QMenu *contextMenu = new QMenu(i18n("KwikDisk")); 0061 0062 m_actionSeparator = contextMenu->addSeparator(); 0063 0064 contextMenu->addAction( 0065 QIcon::fromTheme(QStringLiteral( "kdf" )), 0066 i18n("&Start KDiskFree"), this, &KwikDisk::startKDF); 0067 0068 contextMenu->addAction( 0069 QIcon::fromTheme(QStringLiteral( "configure" )), 0070 i18n("&Configure KwikDisk..."), this, &KwikDisk::changeSettings); 0071 0072 contextMenu->addAction( 0073 QIcon::fromTheme(QStringLiteral( "help-contents" )), 0074 KStandardGuiItem::help().text(), this, &KwikDisk::invokeHelp); 0075 0076 setContextMenu(contextMenu); 0077 0078 setStatus(KStatusNotifierItem::Active); 0079 0080 loadSettings(); 0081 updateDF(); 0082 } 0083 0084 void KwikDisk::enterEvent(QEvent *) 0085 { 0086 qCDebug(KDF); 0087 m_inside = true; 0088 } 0089 0090 void KwikDisk::leaveEvent(QEvent *) 0091 { 0092 qCDebug(KDF); 0093 m_inside = false; 0094 } 0095 0096 void KwikDisk::activate(const QPoint &pos) 0097 { 0098 Q_UNUSED(pos); 0099 qCDebug(KDF); 0100 0101 if( m_dirty ) 0102 updateDF(); 0103 } 0104 0105 void KwikDisk::loadSettings() 0106 { 0107 qCDebug(KDF); 0108 0109 m_options.updateConfiguration(); 0110 setUpdateFrequency( m_options.updateFrequency() ); 0111 } 0112 0113 void KwikDisk::setUpdateFrequency(int frequency) 0114 { 0115 qCDebug(KDF); 0116 0117 // 0118 // Kill current timer and restart it if the frequency is 0119 // larger than zero. 0120 // 0121 QAbstractEventDispatcher::instance()->unregisterTimers(this); 0122 if( frequency > 0 ) 0123 { 0124 startTimer(frequency * 1000); 0125 } 0126 } 0127 0128 /** 0129 * Mark the list as dirty thus forcing a reload the next time the 0130 * popup menu is about to become visible. Note: A current visible popup 0131 * will not be updated now. 0132 */ 0133 void KwikDisk::timerEvent(QTimerEvent *) 0134 { 0135 qCDebug(KDF); 0136 m_dirty = true; 0137 } 0138 0139 void KwikDisk::updateDF() 0140 { 0141 qCDebug(KDF); 0142 0143 m_readingDF = true; 0144 m_diskList.readFSTAB(); 0145 m_diskList.readDF(); 0146 } 0147 0148 void KwikDisk::clearDeviceActions() 0149 { 0150 QList<QAction*> listActions = m_actionGroup->actions(); 0151 QMutableListIterator<QAction*> it(listActions); 0152 while( it.hasNext() ) 0153 { 0154 QAction * action = it.next(); 0155 m_actionGroup->removeAction( action ); 0156 contextMenu()->removeAction( action ); 0157 delete action; 0158 } 0159 } 0160 void KwikDisk::updateDFDone() 0161 { 0162 qCDebug(KDF); 0163 0164 m_readingDF = false; 0165 m_dirty = false; 0166 0167 clearDeviceActions(); 0168 0169 int itemNo = 0; 0170 0171 DisksConstIterator itr = m_diskList.disksConstIteratorBegin(); 0172 DisksConstIterator end = m_diskList.disksConstIteratorEnd(); 0173 for (; itr != end; ++itr) 0174 { 0175 DiskEntry * disk = *itr; 0176 0177 QString toolTipText = QStringLiteral("%1 (%2) %3 on %4") 0178 .arg( disk->mounted() ? i18nc("Unmount the storage device", "Unmount") : i18nc("Mount the storage device", "Mount") ) 0179 .arg( disk->fsType().trimmed() ).arg( disk->deviceName().trimmed() ).arg( disk->mountPoint().trimmed() ); 0180 0181 QString entryName = disk->mountPoint().trimmed(); 0182 if( disk->mounted() ) 0183 { 0184 entryName += QStringLiteral("\t[%1]").arg(disk->prettyKBAvail()); 0185 } 0186 0187 QAction * action = new QAction(entryName, m_actionGroup); 0188 action->setToolTip( toolTipText ); 0189 action->setData( itemNo ); 0190 itemNo++; 0191 0192 QPixmap pix = QIcon::fromTheme(disk->iconName()).pixmap(QSize(32,32)); 0193 0194 if( getuid() !=0 && !disk->mountOptions().contains(QLatin1String( "user" ),Qt::CaseInsensitive) ) 0195 { 0196 QPainter painter( &pix ); 0197 QPixmap lockedPixmap = QIcon::fromTheme(QStringLiteral( "object-locked" )).pixmap(QSize(16,16)); 0198 painter.drawPixmap( QRect(0,0,16,16) , lockedPixmap, QRect(0,0,16,16)); 0199 painter.end(); 0200 0201 toolTipText = i18n("You must login as root to mount this disk"); 0202 action->setToolTip( toolTipText ); 0203 } 0204 0205 if( disk->mounted() ) 0206 { 0207 QPainter painter ( &pix ); 0208 QPixmap mountedPixmap = QIcon::fromTheme(QStringLiteral( "emblem-mounted" )).pixmap(QSize(16,16)); 0209 painter.drawPixmap( QRect(8,8,16,16) , mountedPixmap, QRect(0,0,16,16) ); 0210 painter.end(); 0211 } 0212 0213 action->setIcon( pix ); 0214 0215 } 0216 0217 contextMenu()->insertActions( m_actionSeparator, m_actionGroup->actions() ); 0218 0219 } 0220 0221 void KwikDisk::toggleMount(QAction * action) 0222 { 0223 qCDebug(KDF); 0224 if ( !action ) 0225 return; 0226 0227 DiskEntry *disk = m_diskList.at( action->data().toInt() ); 0228 if( disk == nullptr ) 0229 { 0230 return; 0231 } 0232 0233 int val = disk->toggleMount(); 0234 if( val != 0 ) 0235 { 0236 KMessageBox::error(nullptr, disk->lastSysError()); 0237 } 0238 else if( m_options.openFileManager() && ( disk->mounted() ) ) 0239 { 0240 qCDebug(KDF) << "opening filemanager"; 0241 if( !m_options.fileManager().isEmpty() ) 0242 { 0243 QString cmd = m_options.fileManager(); 0244 int pos = cmd.indexOf(QLatin1String( "%m" )); 0245 if( pos > 0 ) 0246 { 0247 cmd.replace( pos, 2, KShell::quoteArg(disk->mountPoint()) ); 0248 } 0249 else 0250 { 0251 cmd += QLatin1Char( ' ' ) + KShell::quoteArg(disk->mountPoint()); 0252 } 0253 QStringList argList = cmd.split(QLatin1Char( ' ' ), Qt::SkipEmptyParts); 0254 cmd = argList.takeFirst(); 0255 QProcess::startDetached(cmd, argList); 0256 } 0257 } 0258 m_dirty = true; 0259 } 0260 0261 void KwikDisk::criticallyFull(DiskEntry *disk) 0262 { 0263 qCDebug(KDF); 0264 0265 if( m_options.popupIfFull()) 0266 { 0267 QString msg = i18n("Device [%1] on [%2] is critically full.", 0268 disk->deviceName(), disk->mountPoint()); 0269 KMessageBox::error( nullptr, msg, i18nc("Device is getting critically full", "Warning")); 0270 } 0271 } 0272 0273 void KwikDisk::changeSettings() 0274 { 0275 if( m_optionDialog == nullptr ) 0276 { 0277 m_optionDialog = new COptionDialog(nullptr); 0278 if( !m_optionDialog ) 0279 return; 0280 connect(m_optionDialog, &COptionDialog::valueChanged, 0281 this, &KwikDisk::loadSettings); 0282 } 0283 m_optionDialog->show(); 0284 } 0285 0286 void KwikDisk::startKDF() 0287 { 0288 qCDebug(KDF); 0289 0290 auto *job = new KIO::CommandLauncherJob(QStringLiteral("kdf")); 0291 job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, nullptr)); 0292 job->start(); 0293 } 0294 0295 void KwikDisk::invokeHelp() 0296 { 0297 KHelpClient::invokeHelp(QLatin1String(""), QStringLiteral("kdf")); 0298 } 0299 0300 /*****************************************************************************/ 0301 0302 int main(int argc, char **argv) 0303 { 0304 QApplication app(argc, argv); 0305 0306 KLocalizedString::setApplicationDomain(QByteArrayLiteral("kdf")); 0307 0308 KAboutData aboutData(QStringLiteral("kwikdisk"), 0309 i18n("KwikDisk"), 0310 QStringLiteral(KDF_VERSION_STRING), 0311 i18n("KDE Free disk space utility"), 0312 KAboutLicense::GPL, 0313 i18n("(C) 2004 Stanislav Karchebny"), 0314 QString(), 0315 QStringLiteral("https://apps.kde.org/kdf"), 0316 QStringLiteral("Stanislav.Karchebny@kdemail.net")); 0317 0318 aboutData.addAuthor(i18n("Michael Kropfberger"), 0319 i18n("Original author"), 0320 QStringLiteral("michael.kropfberger@gmx.net")); 0321 aboutData.addAuthor(i18n("Espen Sand"), 0322 i18n("KDE 2 changes")); 0323 aboutData.addAuthor(i18n("Stanislav Karchebny"), 0324 i18n("KDE 3 changes"), 0325 QStringLiteral("Stanislav.Karchebny@kdemail.net")); 0326 0327 QCommandLineParser parser; 0328 parser.setApplicationDescription(aboutData.shortDescription()); 0329 0330 aboutData.setupCommandLine(&parser); 0331 0332 KAboutData::setApplicationData(aboutData); 0333 0334 // do the command line parsing 0335 parser.process(app); 0336 0337 // handle standard options 0338 aboutData.processCommandLine(&parser); 0339 0340 KwikDisk mainWin; 0341 0342 //Avoid quit when closing the KwikDisk Settings dialog 0343 app.setQuitOnLastWindowClosed( false ); 0344 0345 // mainWin has WDestructiveClose flag by default, so it will delete itself. 0346 return app.exec(); 0347 } 0348 0349 /*****************************************************************************/ 0350 0351 0352 0353 #include "moc_kwikdisk.cpp"