1/*
2 kwikdisk.cpp - KDiskFree
3
4 Copyright (C) 1999 by Michael Kropfberger <michael.kropfberger@gmx.net>
5 2009 Dario Andres Rodriguez <andresbajotierra@gmail.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
21 */
22
23//
24// 1999-12-03 Espen Sand
25// Cleanups, improvements and fixes for KDE-2
26//
27// 2004-07-15 Stanislav Karchebny
28// Rewrite for KDE 3
29//
30
31#include "kwikdisk.h"
32
33#include <stdlib.h>
34#include <unistd.h>
35
36#include <QtCore/QFile>
37#include <QtCore/QAbstractEventDispatcher>
38
39#include <QtGui/QPainter>
40#include <QtGui/QPixmap>
41#include <QtGui/QActionGroup>
42
43#include <klocale.h>
44#include <kapplication.h>
45#include <kaboutdata.h>
46#include <kcmdlineargs.h>
47#include <kmessagebox.h>
48#include <kmenu.h>
49#include <krun.h>
50#include <ktoolinvocation.h>
51#include <kshell.h>
52#include <kdebug.h>
53
54static const char description[] =
55 I18N_NOOP("KDE Free disk space utility");
56
57static const char version[] = "0.4";
58
59/*****************************************************************************/
60
61KwikDisk::KwikDisk()
62 : KSystemTrayIcon()
63 , m_readingDF(false)
64 , m_dirty(true)
65 , m_inside(false)
66 , m_optionDialog(0)
67{
68 kDebug() ;
69
70 contextMenu()->setTitle(i18n("KwikDisk"));
71 setIcon(KSystemTrayIcon::loadIcon(QLatin1String( "kdf" )));
72 show();
73
74 connect( &m_diskList, SIGNAL(readDFDone()), this, SLOT(updateDFDone()) );
75 connect( &m_diskList, SIGNAL(criticallyFull(DiskEntry*)),
76 this, SLOT(criticallyFull(DiskEntry*)) );
77
78 connect( this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
79 SLOT(slotActivated(QSystemTrayIcon::ActivationReason)));
80
81 m_actionGroup = new QActionGroup( this );
82 connect( m_actionGroup, SIGNAL(triggered(QAction*)) , this, SLOT(toggleMount(QAction*)) );
83
84 m_actionSeparator = contextMenu()->addSeparator();
85
86 contextMenu()->addAction(
87 KSystemTrayIcon::loadIcon(QLatin1String( "kdf" )),
88 i18n("&Start KDiskFree"), this, SLOT(startKDF()));
89
90 contextMenu()->addAction(
91 KSystemTrayIcon::loadIcon(QLatin1String( "configure" )),
92 i18n("&Configure KwikDisk..."), this, SLOT(changeSettings()));
93
94 contextMenu()->addAction(
95 KSystemTrayIcon::loadIcon(QLatin1String( "help-contents" )),
96 KStandardGuiItem::help().text(), this, SLOT(invokeHelp()));
97
98 loadSettings();
99 updateDF();
100
101}
102
103void KwikDisk::enterEvent(QEvent *)
104{
105 kDebug() ;
106 m_inside = true;
107}
108
109void KwikDisk::leaveEvent(QEvent *)
110{
111 kDebug() ;
112 m_inside = false;
113}
114
115void KwikDisk::slotActivated(QSystemTrayIcon::ActivationReason)
116{
117 kDebug() ;
118
119 if( m_dirty )
120 updateDF();
121}
122
123void KwikDisk::loadSettings()
124{
125 kDebug() ;
126
127 m_options.updateConfiguration();
128 setUpdateFrequency( m_options.updateFrequency() );
129}
130
131void KwikDisk::setUpdateFrequency(int frequency)
132{
133 kDebug() ;
134
135 //
136 // Kill current timer and restart it if the frequency is
137 // larger than zero.
138 //
139 QAbstractEventDispatcher::instance()->unregisterTimers(this);
140 if( frequency > 0 )
141 {
142 startTimer(frequency * 1000);
143 }
144}
145
146/**
147 * Mark the list as dirty thus forcing a reload the next time the
148 * popup menu is about to become visible. Note: A current visible popup
149 * will not be updated now.
150 */
151void KwikDisk::timerEvent(QTimerEvent *)
152{
153 kDebug() ;
154 m_dirty = true;
155}
156
157void KwikDisk::updateDF()
158{
159 kDebug() ;
160
161 m_readingDF = true;
162 m_diskList.readFSTAB();
163 m_diskList.readDF();
164}
165
166void KwikDisk::clearDeviceActions()
167{
168 QList<QAction*> listActions = m_actionGroup->actions();
169 QMutableListIterator<QAction*> it(listActions);
170 while( it.hasNext() )
171 {
172 QAction * action = it.next();
173 m_actionGroup->removeAction( action );
174 contextMenu()->removeAction( action );
175 delete action;
176 }
177}
178void KwikDisk::updateDFDone()
179{
180 kDebug() ;
181
182 m_readingDF = false;
183 m_dirty = false;
184
185 clearDeviceActions();
186
187 int itemNo = 0;
188
189 DisksConstIterator itr = m_diskList.disksConstIteratorBegin();
190 DisksConstIterator end = m_diskList.disksConstIteratorEnd();
191 for (; itr != end; ++itr)
192 {
193 DiskEntry * disk = *itr;
194
195 QString toolTipText = QString::fromLatin1("%1 (%2) %3 on %4")
196 .arg( disk->mounted() ? i18nc("Unmount the storage device", "Unmount") : i18nc("Mount the storage device", "Mount") )
197 .arg( disk->fsType().trimmed() ).arg( disk->deviceName().trimmed() ).arg( disk->mountPoint().trimmed() );
198
199 QString entryName = disk->mountPoint().trimmed();
200 if( disk->mounted() )
201 {
202 entryName += QString::fromLatin1("\t[%1]").arg(disk->prettyKBAvail());
203 }
204
205 QAction * action = new QAction(entryName, m_actionGroup);
206 action->setToolTip( toolTipText );
207 action->setData( itemNo );
208 itemNo++;
209
210 QPixmap pix = KSystemTrayIcon::loadIcon(disk->iconName()).pixmap( QSize(32,32) );
211
212 if( getuid() !=0 && !disk->mountOptions().contains(QLatin1String( "user" ),Qt::CaseInsensitive) )
213 {
214 QPainter painter( &pix );
215 painter.drawPixmap( QRect(0,0,16,16) , SmallIcon(QLatin1String( "object-locked" )), QRect(0,0,16,16));
216 painter.end();
217
218 toolTipText = i18n("You must login as root to mount this disk");
219 action->setToolTip( toolTipText );
220 }
221
222 if( disk->mounted() )
223 {
224 QPainter painter ( &pix );
225 painter.drawPixmap( QRect(8,8,16,16) , SmallIcon(QLatin1String( "emblem-mounted" )), QRect(0,0,16,16) );
226 painter.end();
227 }
228
229 action->setIcon( pix );
230
231 }
232
233 contextMenu()->insertActions( m_actionSeparator, m_actionGroup->actions() );
234
235}
236
237void KwikDisk::toggleMount(QAction * action)
238{
239 kDebug() ;
240 if ( !action )
241 return;
242
243 DiskEntry *disk = m_diskList.at( action->data().toInt() );
244 if( disk == 0 )
245 {
246 return;
247 }
248
249 int val = disk->toggleMount();
250 if( val != 0 )
251 {
252 KMessageBox::error(0, disk->lastSysError());
253 }
254 else if( (m_options.openFileManager() == true) && (disk->mounted() == true ) )
255 {
256 kDebug() << "opening filemanager" ;
257 if( m_options.fileManager().isEmpty() == false )
258 {
259 QString cmd = m_options.fileManager();
260 int pos = cmd.indexOf(QLatin1String( "%m" ));
261 if( pos > 0 )
262 {
263 cmd = cmd.replace( pos, 2, KShell::quoteArg(disk->mountPoint()) ) + QLatin1String( " &" );
264 }
265 else
266 {
267 cmd += QLatin1Char( ' ' ) + KShell::quoteArg(disk->mountPoint()) +QLatin1String( " &" );
268 }
269 system( QFile::encodeName(cmd) );
270 }
271 }
272 m_dirty = true;
273}
274
275void KwikDisk::criticallyFull(DiskEntry *disk)
276{
277 kDebug() ;
278
279 if( m_options.popupIfFull())
280 {
281 QString msg = i18n("Device [%1] on [%2] is critically full.",
282 disk->deviceName(), disk->mountPoint());
283 KMessageBox::sorry( 0, msg, i18nc("Device is getting critically full", "Warning"));
284 }
285}
286
287void KwikDisk::changeSettings()
288{
289 if( m_optionDialog == 0 )
290 {
291 m_optionDialog = new COptionDialog(0);
292 if( !m_optionDialog )
293 return;
294 connect(m_optionDialog, SIGNAL(valueChanged()),
295 this, SLOT(loadSettings()));
296 }
297 m_optionDialog->show();
298}
299
300void KwikDisk::startKDF()
301{
302 kDebug() ;
303
304 KRun::runCommand(QLatin1String( "kdf" ),NULL);
305}
306
307void KwikDisk::invokeHelp()
308{
309 KToolInvocation::invokeHelp(QLatin1String( "" ), QLatin1String( "kdf" ));
310}
311
312/*****************************************************************************/
313
314int main(int argc, char **argv)
315{
316 KAboutData about("kwikdisk", "kdf", ki18n("KwikDisk"), version, ki18n(description),
317 KAboutData::License_GPL, ki18n("(C) 2004 Stanislav Karchebny"),
318 KLocalizedString(), "http://utils.kde.org/projects/kdf",
319 "Stanislav.Karchebny@kdemail.net");
320 about.addAuthor( ki18n("Michael Kropfberger"), ki18n("Original author"),
321 "michael.kropfberger@gmx.net" );
322 about.addAuthor( ki18n("Espen Sand"), ki18n("KDE 2 changes"));
323 about.addAuthor( ki18n("Stanislav Karchebny"), ki18n("KDE 3 changes"),
324 "Stanislav.Karchebny@kdemail.net" );
325 KCmdLineArgs::init(argc, argv, &about);
326
327 KCmdLineOptions options;
328 KCmdLineArgs::addCmdLineOptions( options );
329 KApplication app;
330
331 KwikDisk mainWin;
332
333 //Avoid quit when closing the KwikDisk Settings dialog
334 app.setQuitOnLastWindowClosed( false );
335
336 // mainWin has WDestructiveClose flag by default, so it will delete itself.
337 return app.exec();
338}
339
340/*****************************************************************************/
341
342#include "kwikdisk.moc"
343
344