diff --git a/krusader/MountMan/kmountman.cpp b/krusader/MountMan/kmountman.cpp index 267cc2d1..309f000a 100644 --- a/krusader/MountMan/kmountman.cpp +++ b/krusader/MountMan/kmountman.cpp @@ -1,526 +1,528 @@ /*************************************************************************** kmountman.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "kmountman.h" -#include -#include -#include +// QtCore +#include +// QtWidgets +#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krglobal.h" #include "../kractions.h" #include "../defaults.h" #include "../Dialogs/krdialogs.h" #include "../krservices.h" #include "kmountmangui.h" #include "../VFS/krpermhandler.h" #ifdef _OS_SOLARIS_ #define FSTAB "/etc/vfstab" #else #define FSTAB "/etc/fstab" #endif static int __delayedIdx; // ugly: pass the processEvents deadlock KMountMan::KMountMan(QWidget *parent) : QObject(), Operational(false), waiting(false), mountManGui(0), parentWindow(parent) { _actions = 0L; _action = new KToolBarPopupAction(QIcon::fromTheme("kr_mountman"), i18n("&MountMan..."), this); connect(_action, SIGNAL(triggered(bool)), SLOT(mainWindow())); connect(_action->menu(), SIGNAL(aboutToShow()), SLOT(quickList())); // added as a precaution, although we use kde services now if (!KrServices::cmdExist("mount")) { Operational = false; } else { Operational = true; } network_fs << "nfs" << "smbfs" << "fuse.fusesmb" << "fuse.sshfs"; //TODO: is this list complete ? // list of FS that we don't manage at all invalid_fs << "swap" << "/dev/pts" << "tmpfs" << "devpts" << "sysfs" << "rpc_pipefs" << "usbfs" << "binfmt_misc"; #ifdef BSD invalid_fs << "procfs"; #else invalid_fs << "proc"; #endif // list of FS that we don't allow to mount/unmount nonmount_fs << "supermount"; { KConfigGroup group(krConfig, "Advanced"); QStringList nonmount = group.readEntry("Nonmount Points", _NonMountPoints).split(','); nonmount_fs_mntpoint += nonmount; // simplify the white space for (QStringList::Iterator it = nonmount_fs_mntpoint.begin(); it != nonmount_fs_mntpoint.end(); ++it) { *it = (*it).simplified(); } } } KMountMan::~KMountMan() {} bool KMountMan::invalidFilesystem(QString type) { return (invalid_fs.contains(type) > 0); } // this is an ugly hack, but type can actually be a mountpoint. oh well... bool KMountMan::nonmountFilesystem(QString type, QString mntPoint) { return((nonmount_fs.contains(type) > 0) || (nonmount_fs_mntpoint.contains(mntPoint) > 0)); } bool KMountMan::networkFilesystem(QString type) { return (network_fs.contains(type) > 0); } void KMountMan::mainWindow() { // left as a precaution, although we use kde's services now if (!KrServices::cmdExist("mount")) { KMessageBox::error(0, i18n("Cannot start 'mount'. Check the 'Dependencies' page in konfigurator.")); return; } mountManGui = new KMountManGUI(this); delete mountManGui; /* as KMountManGUI is modal, we can now delete it */ mountManGui = 0; /* for sanity */ } QExplicitlySharedDataPointer KMountMan::findInListByMntPoint(KMountPoint::List &lst, QString value) { if (value.length() > 1 && value.endsWith('/')) value = value.left(value.length() - 1); QExplicitlySharedDataPointer m; for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) { m = it->data(); QString mntPnt = m->mountPoint(); if (mntPnt.length() > 1 && mntPnt.endsWith('/')) mntPnt = mntPnt.left(mntPnt.length() - 1); if (mntPnt == value) return m; } return QExplicitlySharedDataPointer(); } void KMountMan::jobResult(KJob *job) { waiting = false; if (job->error()) job->uiDelegate()->showErrorMessage(); } void KMountMan::mount(QString mntPoint, bool blocking) { QString udi = findUdiForPath(mntPoint, Solid::DeviceInterface::StorageAccess); if (!udi.isNull()) { Solid::Device device(udi); Solid::StorageAccess *access = device.as(); if (access && !access->isAccessible()) { connect(access, SIGNAL(setupDone(Solid::ErrorType, QVariant, const QString &)), this, SLOT(slotSetupDone(Solid::ErrorType, QVariant, const QString &))); if (blocking) waiting = true; // prepare to block access->setup(); } } else { KMountPoint::List possible = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions); QExplicitlySharedDataPointer m = findInListByMntPoint(possible, mntPoint); if (!((bool)m)) return; if (blocking) waiting = true; // prepare to block // KDE4 doesn't allow mounting devices as user, because they think it's the right behaviour. // I add this patch, as I don't think so. if (geteuid()) { // tries to mount as an user? KProcess proc; proc << KrServices::fullPathName("mount") << mntPoint; proc.start(); if (!blocking) return; proc.waitForFinished(-1); // -1 msec blocks without timeout if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) return; } KIO::SimpleJob *job = KIO::mount(false, m->mountType().toLocal8Bit(), m->mountedFrom(), m->mountPoint(), KIO::DefaultFlags); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); connect(job, SIGNAL(result(KJob*)), this, SLOT(jobResult(KJob*))); } while (blocking && waiting) { qApp->processEvents(); usleep(1000); } } void KMountMan::unmount(QString mntPoint, bool blocking) { //if working dir is below mountpoint cd to ~ first if(QUrl::fromLocalFile(QDir(mntPoint).canonicalPath()).isParentOf(QUrl::fromLocalFile(QDir::current().canonicalPath()))) QDir::setCurrent(QDir::homePath()); QString udi = findUdiForPath(mntPoint, Solid::DeviceInterface::StorageAccess); if (!udi.isNull()) { Solid::Device device(udi); Solid::StorageAccess *access = device.as(); if (access && access->isAccessible()) { connect(access, SIGNAL(teardownDone(Solid::ErrorType, QVariant, const QString &)), this, SLOT(slotTeardownDone(Solid::ErrorType, QVariant, const QString &))); access->teardown(); } } else { if (blocking) waiting = true; // prepare to block // KDE4 doesn't allow unmounting devices as user, because they think it's the right behaviour. // I add this patch, as I don't think so. if (geteuid()) { // tries to mount as an user? KProcess proc; proc << KrServices::fullPathName("umount") << mntPoint; proc.start(); if (!blocking) return; proc.waitForFinished(-1); // -1 msec blocks without timeout if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) return; } KIO::SimpleJob *job = KIO::unmount(mntPoint, KIO::DefaultFlags); job->setUiDelegate(new KIO::JobUiDelegate()); KIO::getJobTracker()->registerJob(job); connect(job, SIGNAL(result(KJob*)), this, SLOT(jobResult(KJob*))); } while (blocking && waiting) { qApp->processEvents(); usleep(1000); } } KMountMan::mntStatus KMountMan::getStatus(QString mntPoint) { KMountPoint::List::iterator it; QExplicitlySharedDataPointer m; // 1: is it already mounted KMountPoint::List current = KMountPoint::currentMountPoints(); m = findInListByMntPoint(current, mntPoint); if ((bool)m) return MOUNTED; // 2: is it a mount point but not mounted? KMountPoint::List possible = KMountPoint::possibleMountPoints(); m = findInListByMntPoint(possible, mntPoint); if ((bool)m) return NOT_MOUNTED; // 3: unknown return DOESNT_EXIST; } void KMountMan::toggleMount(QString mntPoint) { mntStatus status = getStatus(mntPoint); switch (status) { case MOUNTED: unmount(mntPoint); break; case NOT_MOUNTED: mount(mntPoint); break; case DOESNT_EXIST: // do nothing: no-op to make the compiler quiet ;-) break; } } void KMountMan::autoMount(QString path) { if (getStatus(path) == NOT_MOUNTED) mount(path); } void KMountMan::eject(QString mntPoint) { QString udi = findUdiForPath(mntPoint, Solid::DeviceInterface::OpticalDrive); if (udi.isNull()) return; Solid::Device dev(udi); Solid::OpticalDrive *drive = dev.as(); if (drive == 0) return; //if working dir is below mountpoint cd to ~ first if(QUrl::fromLocalFile(QDir(mntPoint).canonicalPath()).isParentOf(QUrl::fromLocalFile(QDir::current().canonicalPath()))) QDir::setCurrent(QDir::homePath()); connect(drive, SIGNAL(ejectDone(Solid::ErrorType, QVariant, const QString &)), this, SLOT(slotTeardownDone(Solid::ErrorType, QVariant, const QString &))); drive->eject(); } // returns true if the path is an ejectable mount point (at the moment CDROM and DVD) bool KMountMan::ejectable(QString path) { QString udi = findUdiForPath(path, Solid::DeviceInterface::OpticalDisc); if (udi.isNull()) return false; Solid::Device dev(udi); return dev.as() != 0; } bool KMountMan::removable(QString path) { QString udi = findUdiForPath(path, Solid::DeviceInterface::StorageAccess); if (udi.isNull()) return false; return removable(Solid::Device(udi)); } bool KMountMan::removable(Solid::Device d) { if(!d.isValid()) return false; Solid::StorageDrive *drive = d.as(); if(drive) return drive->isRemovable(); else return(removable(d.parent())); } // a mountMan special version of KIO::convertSize, which deals // with large filesystems ==> > 4GB, it actually receives size in // a minimum block of 1024 ==> data is KB not bytes QString KMountMan::convertSize(KIO::filesize_t size) { float fsize; QString s; QLocale loc; // Tera-byte if (size >= 1073741824) { fsize = (float) size / (float) 1073741824; if (fsize > 1024) // no name for something bigger than tera byte // let's call it Zega-Byte, who'll ever find out? :-) s = i18n("%1 ZB", loc.toString(fsize / (float) 1024, 'f', 1)); else s = i18n("%1 TB", loc.toString(fsize, 'f', 1)); } // Giga-byte else if (size >= 1048576) { fsize = (float) size / (float) 1048576; s = i18n("%1 GB", loc.toString(fsize, 'f', 1)); } // Mega-byte else if (size > 1024) { fsize = (float) size / (float) 1024; s = i18n("%1 MB", loc.toString(fsize, 'f', 1)); } // Kilo-byte else { fsize = (float) size; s = i18n("%1 KB", loc.toString(fsize, 'f', 0)); } return s; } // populate the pop-up menu of the mountman tool-button with actions void KMountMan::quickList() { if (!Operational) { KMessageBox::error(0, i18n("MountMan is not operational. Sorry")); return ; } // clear the popup menu _action->menu() ->clear(); // create lists of current and possible mount points KMountPoint::List current = KMountPoint::currentMountPoints(); KMountPoint::List possible = KMountPoint::possibleMountPoints(); // create a menu, displaying mountpoints with possible actions // also, populate a small array with the actions if (_actions) delete[] _actions; _actions = new QString[ possible.size()]; KMountPoint::List::iterator it; QExplicitlySharedDataPointer m; int idx; for (it = possible.begin(), idx = 0; it != possible.end(); ++it, ++idx) { m = it->data(); // skip nonmountable file systems if (nonmountFilesystem(m->mountType(), m->mountPoint()) || invalidFilesystem(m->mountType())) continue; // does the mountpoint exist in current list? if so, it can only // be umounted, otherwise, it can be mounted bool needUmount = false; KMountPoint::List::iterator otherIt; for (otherIt = current.begin(); otherIt != current.end(); ++otherIt) { if ((*otherIt) ->mountPoint() == m->mountPoint()) { // found it, in needs umount needUmount = true; break; } } // add the item to the menu _actions[ idx ] = QString(needUmount ? "_U_" : "_M_") + m->mountPoint(); QString text = QString((needUmount ? i18n("Unmount") : i18n("Mount"))) + ' ' + m->mountPoint() + " (" + m->mountedFrom() + ')'; QAction * act = _action->menu() ->addAction(text); act->setData(QVariant(idx)); } connect(_action->menu(), SIGNAL(triggered(QAction *)), this, SLOT(delayedPerformAction(QAction *))); } void KMountMan::delayedPerformAction(QAction * act) { int idx = -1; if (act && act->data().canConvert()) idx = act->data().toInt(); __delayedIdx = idx; if (idx < 0) return ; QTimer::singleShot(0, this, SLOT(performAction())); } void KMountMan::performAction() { if (_actions == 0 || __delayedIdx < 0) // for sanity return; // ugly !!! take idx from the value put there by delayedPerformAction so // as to NOT DIE because of a processEvents deadlock!!! @#$@!@ int idx = __delayedIdx; bool domount = _actions[ idx ].left(3) == "_M_"; QString mountPoint = _actions[ idx ].mid(3); if (!domount) { // umount unmount(mountPoint); } else { // mount mount(mountPoint); } // free memory delete[] _actions; _actions = 0L; disconnect(_action->menu(), SIGNAL(triggered(QAction *)), 0, 0); } QString KMountMan::findUdiForPath(QString path, const Solid::DeviceInterface::Type &expType) { KMountPoint::List current = KMountPoint::currentMountPoints(); KMountPoint::List possible = KMountPoint::possibleMountPoints(); QExplicitlySharedDataPointer mp = findInListByMntPoint(current, path); if (!(bool)mp) { mp = findInListByMntPoint(possible, path); if (!(bool)mp) return QString(); } QString dev = QDir(mp->mountedFrom()).canonicalPath(); QList storageDevices = Solid::Device::listFromType(Solid::DeviceInterface::Block); for (int p = storageDevices.count() - 1 ; p >= 0; p--) { Solid::Device device = storageDevices[ p ]; QString udi = device.udi(); Solid::Block * sb = device.as(); if (sb) { QString devb = QDir(sb->device()).canonicalPath(); if (expType != Solid::DeviceInterface::Unknown && !device.isDeviceInterface(expType)) continue; if (devb == dev) return udi; } } return QString(); } QString KMountMan::pathForUdi(QString udi) { Solid::Device device(udi); Solid::StorageAccess *access = device.as(); if(access) return access->filePath(); else return QString(); } void KMountMan::slotTeardownDone(Solid::ErrorType error, QVariant errorData, const QString& /*udi*/) { waiting = false; if (error != Solid::NoError && errorData.isValid()) { KMessageBox::sorry(parentWindow, errorData.toString()); } } void KMountMan::slotSetupDone(Solid::ErrorType error, QVariant errorData, const QString& /*udi*/) { waiting = false; if (error != Solid::NoError && errorData.isValid()) { KMessageBox::sorry(parentWindow, errorData.toString()); } } diff --git a/krusader/MountMan/kmountman.h b/krusader/MountMan/kmountman.h index 6b306368..064d6a93 100644 --- a/krusader/MountMan/kmountman.h +++ b/krusader/MountMan/kmountman.h @@ -1,124 +1,126 @@ /*************************************************************************** kmountman.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KMOUNTMAN_H #define KMOUNTMAN_H -#include -#include -#include -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include +#include +// QtWidgets +#include +#include #include #include #include #include #include class KMountManGUI; class QAction; class KToolBarPopupAction; class KMountMan : public QObject { Q_OBJECT friend class KMountManGUI; public: enum mntStatus {DOESNT_EXIST, NOT_MOUNTED, MOUNTED}; inline bool operational() { return Operational; } // check this 1st void mount(QString mntPoint, bool blocking = true); // this is probably what you need for mount void unmount(QString mntPoint, bool blocking = true); // this is probably what you need for unmount mntStatus getStatus(QString mntPoint); // return the status of a mntPoint (if any) void autoMount(QString path); // just call it before refreshing into a dir void eject(QString mntPoint); bool ejectable(QString path); bool removable(QString path); bool removable(Solid::Device d); QString convertSize(KIO::filesize_t size); bool invalidFilesystem(QString type); bool networkFilesystem(QString type); bool nonmountFilesystem(QString type, QString mntPoint); QAction *action() { return (QAction *) _action; } KMountMan(QWidget *parent); ~KMountMan(); QString findUdiForPath(QString path, const Solid::DeviceInterface::Type &expType = Solid::DeviceInterface::Unknown); QString pathForUdi(QString udi); public slots: void mainWindow(); // opens up the GUI void delayedPerformAction(QAction *); void performAction(); void quickList(); protected slots: void jobResult(KJob *job); void slotTeardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi); void slotSetupDone(Solid::ErrorType error, QVariant errorData, const QString &udi); protected: // used internally static QExplicitlySharedDataPointer findInListByMntPoint(KMountPoint::List &lst, QString value); void toggleMount(QString mntPoint); void emitRefreshPanel(const QUrl &url) { emit refreshPanel(url); } signals: void refreshPanel(const QUrl &); private: QString *_actions; KToolBarPopupAction *_action; bool Operational; // if false, something went terribly wrong on startup bool waiting; // used to block krusader while waiting for (un)mount operation KMountManGUI *mountManGui; // the following is the FS type QStringList invalid_fs; QStringList nonmount_fs; QStringList network_fs; // the following is the FS name QStringList nonmount_fs_mntpoint; QPointer parentWindow; }; #endif diff --git a/krusader/MountMan/kmountmangui.cpp b/krusader/MountMan/kmountmangui.cpp index 1457a6cf..84cade40 100644 --- a/krusader/MountMan/kmountmangui.cpp +++ b/krusader/MountMan/kmountmangui.cpp @@ -1,539 +1,542 @@ /*************************************************************************** kmountmangui.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "kmountmangui.h" #include "kmountman.h" #include "../krglobal.h" #include "../Dialogs/krspecialwidgets.h" #include "../kicons.h" #include "../defaults.h" #include "../VFS/vfs.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +// QtCore +#include +#include +#include +// QtGui +#include +#include +#include +// QtWidgets +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include #include #include #include #ifndef BSD #define MTAB "/etc/mtab" #endif KMountManGUI::KMountManGUI(KMountMan *mntMan) : QDialog(mntMan->parentWindow), mountMan(mntMan), info(0), mountList(0), cbShowOnlyRemovable(0), watcher(0), sizeX(-1), sizeY(-1) { setWindowTitle(i18n("MountMan - Your Mount-Manager")); setWindowModality(Qt::WindowModal); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); watcher = new QTimer(this); connect(watcher, SIGNAL(timeout()), this, SLOT(checkMountChange())); mainLayout->addLayout(createMainPage()); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); mainLayout->addWidget(buttonBox); ejectButton = new QPushButton(i18n("&Eject")); ejectButton->setIcon(QIcon::fromTheme(QStringLiteral("media-eject"))); ejectButton->setEnabled(false); buttonBox->addButton(ejectButton, QDialogButtonBox::ActionRole); mountButton = new QPushButton(i18n("&Unmount")); mountButton->setEnabled(false); buttonBox->addButton(mountButton, QDialogButtonBox::ActionRole); // connections connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); connect(ejectButton, SIGNAL(clicked()), SLOT(slotEject())); connect(mountButton, SIGNAL(clicked()), SLOT(slotToggleMount())); connect(mountList, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(doubleClicked(QTreeWidgetItem *))); connect(mountList, SIGNAL(itemRightClicked(QTreeWidgetItem *, const QPoint &, int)), this, SLOT(clicked(QTreeWidgetItem*, const QPoint &))); connect(mountList, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(changeActive(QTreeWidgetItem *))); connect(mountList, SIGNAL(itemSelectionChanged()), this, SLOT(changeActive())); KConfigGroup group(krConfig, "MountMan"); int sx = group.readEntry("Window Width", -1); int sy = group.readEntry("Window Height", -1); if (sx != -1 && sy != -1) resize(sx, sy); else resize(600, 300); if (group.readEntry("Window Maximized", false)) showMaximized(); else show(); getSpaceData(); exec(); } KMountManGUI::~KMountManGUI() { watcher->stop(); delete watcher; KConfigGroup group(krConfig, "MountMan"); group.writeEntry("Window Width", sizeX); group.writeEntry("Window Height", sizeY); group.writeEntry("Window Maximized", isMaximized()); group.writeEntry("Last State", mountList->header()->saveState()); group.writeEntry("ShowOnlyRemovable", cbShowOnlyRemovable->isChecked()); } void KMountManGUI::resizeEvent(QResizeEvent *e) { if (!isMaximized()) { sizeX = e->size().width(); sizeY = e->size().height(); } QDialog::resizeEvent(e); } QLayout *KMountManGUI::createMainPage() { QGridLayout *layout = new QGridLayout(); layout->setSpacing(10); mountList = new KrTreeWidget(this); // create the main container KConfigGroup grp(krConfig, "Look&Feel"); mountList->setFont(grp.readEntry("Filelist Font", _FilelistFont)); mountList->setSelectionMode(QAbstractItemView::SingleSelection); mountList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); mountList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); QStringList labels; labels << i18n("Name"); labels << i18n("Type"); labels << i18n("Mnt.Point"); labels << i18n("Total Size"); labels << i18n("Free Size"); labels << i18n("Free %"); mountList->setHeaderLabels(labels); mountList->header()->setSectionResizeMode(QHeaderView::Interactive); grp = KConfigGroup(krConfig, "MountMan"); if (grp.hasKey("Last State")) mountList->header()->restoreState(grp.readEntry("Last State", QByteArray())); else { int i = QFontMetrics(mountList->font()).width("W"); int j = QFontMetrics(mountList->font()).width("0"); j = (i > j ? i : j); mountList->setColumnWidth(0, j*8); mountList->setColumnWidth(1, j*4); mountList->setColumnWidth(2, j*8); mountList->setColumnWidth(3, j*6); mountList->setColumnWidth(4, j*6); mountList->setColumnWidth(5, j*5); } mountList->setAllColumnsShowFocus(true); mountList->header()->setSortIndicatorShown(true); mountList->sortItems(0, Qt::AscendingOrder); // now the list is created, time to fill it with data. //=>mountMan->forceUpdate(); QGroupBox *box = new QGroupBox(i18n("MountMan.Info"), this); box->setAlignment(Qt::AlignHCenter); QVBoxLayout *vboxl = new QVBoxLayout(box); info = new KRFSDisplay(box); vboxl->addWidget(info); info->resize(info->width(), height()); cbShowOnlyRemovable = new QCheckBox(i18n("Show only removable devices"), this); cbShowOnlyRemovable->setChecked(grp.readEntry("ShowOnlyRemovable", false)); connect(cbShowOnlyRemovable , SIGNAL(stateChanged(int)), SLOT(updateList())); layout->addWidget(box, 0, 0); layout->addWidget(cbShowOnlyRemovable, 1, 0); layout->addWidget(mountList, 0, 1, 2, 1); return layout; } void KMountManGUI::getSpaceData() { fileSystems.clear(); KrMountDetector::getInstance()->hasMountsChanged(); mounted = KMountPoint::currentMountPoints(); possible = KMountPoint::possibleMountPoints(); if (mounted.size() == 0) { // nothing is mounted addNonMounted(); updateList(); // let's continue return ; } for (KMountPoint::List::iterator it = mounted.begin(); it != mounted.end(); ++it) { // don't bother with invalid file systems if (mountMan->invalidFilesystem((*it)->mountType())) { continue; } KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo((*it) ->mountPoint()); if(!info.isValid()) { continue; } fsData data; data.setMntPoint((*it) ->mountPoint()); data.setMounted(true); data.setTotalBlks(info.size() / 1024); data.setFreeBlks(info.available() / 1024); data.setName((*it)->mountedFrom()); data.setType((*it)->mountType()); fileSystems.append(data); } addNonMounted(); updateList(); } void KMountManGUI::addNonMounted() { // handle the non-mounted ones for (KMountPoint::List::iterator it = possible.begin(); it != possible.end(); ++it) { // make sure we don't add things we've already added if (KMountMan::findInListByMntPoint(mounted, (*it)->mountPoint())) { continue; } else { fsData data; data.setMntPoint((*it)->mountPoint()); data.setMounted(false); data.setType((*it)->mountType()); data.setName((*it)->mountedFrom()); if (mountMan->invalidFilesystem(data.type())) continue; fileSystems.append(data); } } } void KMountManGUI::addItemToMountList(KrTreeWidget *lst, fsData &fs) { Solid::Device device(mountMan->findUdiForPath(fs.mntPoint(), Solid::DeviceInterface::StorageAccess)); if (cbShowOnlyRemovable->isChecked() && !mountMan->removable(device)) return; bool mtd = fs.mounted(); QString tSize = QString("%1").arg(KIO::convertSizeFromKiB(fs.totalBlks())); QString fSize = QString("%1").arg(KIO::convertSizeFromKiB(fs.freeBlks())); QString sPrct = QString("%1%").arg(100 - (fs.usedPerct())); QTreeWidgetItem *item = new QTreeWidgetItem(lst); item->setText(0, fs.name()); item->setText(1, fs.type()); item->setText(2, fs.mntPoint()); item->setText(3, (mtd ? tSize : QString("N/A"))); item->setText(4, (mtd ? fSize : QString("N/A"))); item->setText(5, (mtd ? sPrct : QString("N/A"))); Solid::StorageVolume *vol = device.as (); QString icon; if(device.isValid()) icon = device.icon(); else if(mountMan->networkFilesystem(fs.type())) icon = "folder-remote"; QStringList overlays; if (mtd) { overlays << "emblem-mounted"; } else { overlays << QString(); // We have to guarantee the placement of the next emblem } if (vol && vol->usage() == Solid::StorageVolume::Encrypted) { overlays << "security-high"; } item->setIcon(0, KDE::icon(icon, overlays)); } void KMountManGUI::updateList() { QString currentMP; int currentIdx = 0; QTreeWidgetItem *currentItem = mountList->currentItem(); if(currentItem) { currentMP = getMntPoint(currentItem); currentIdx = mountList->indexOfTopLevelItem(currentItem); } mountList->clearSelection(); mountList->clear(); for (QList::iterator it = fileSystems.begin(); it != fileSystems.end() ; ++it) addItemToMountList(mountList, *it); currentItem = mountList->topLevelItem(currentIdx); for(int i = 0; i < mountList->topLevelItemCount(); i++) { QTreeWidgetItem *item = mountList->topLevelItem(i); if(getMntPoint(item) == currentMP) currentItem = item; } if(!currentItem) currentItem = mountList->topLevelItem(0); mountList->setCurrentItem(currentItem); changeActive(currentItem); mountList->setFocus(); watcher->setSingleShot(true); watcher->start(WATCHER_DELAY); // starting the watch timer ( single shot ) } void KMountManGUI::checkMountChange() { if (KrMountDetector::getInstance()->hasMountsChanged()) getSpaceData(); watcher->setSingleShot(true); watcher->start(WATCHER_DELAY); // starting the watch timer ( single shot ) } void KMountManGUI::doubleClicked(QTreeWidgetItem *i) { if (!i) return; // we don't want to refresh to swap, do we ? // change the active panel to this mountpoint mountMan->emitRefreshPanel(QUrl::fromLocalFile(getMntPoint(i))); close(); } void KMountManGUI::changeActive() { QList seld = mountList->selectedItems(); if (seld.count() > 0) changeActive(seld[ 0 ]); } // when user clicks on a filesystem, change information void KMountManGUI::changeActive(QTreeWidgetItem *i) { if (!i) { if (info) { info->setEmpty(true); info->update(); } mountButton->setEnabled(false); ejectButton->setEnabled(false); return; } fsData *system = getFsData(i); info->setAlias(system->mntPoint()); info->setRealName(system->name()); info->setMounted(system->mounted()); info->setEmpty(false); info->setTotalSpace(system->totalBlks()); info->setFreeSpace(system->freeBlks()); info->repaint(); if(system->mounted()) mountButton->setText(i18n("&Unmount")); else mountButton->setText(i18n("&Mount")); ejectButton->setEnabled(mountMan->ejectable(system->mntPoint())); mountButton->setEnabled(true); } // called when right-clicked on a filesystem void KMountManGUI::clicked(QTreeWidgetItem *item, const QPoint & pos) { // these are the values that will exist in the menu #define MOUNT_ID 90 #define UNMOUNT_ID 91 #define FORMAT_ID 93 #define EJECT_ID 94 ////////////////////////////////////////////////////////// if (!item) return ; fsData *system = getFsData(item); // create the menu QMenu popup; popup.setTitle(i18n("MountMan")); if (!system->mounted()) { QAction *mountAct = popup.addAction(i18n("Mount")); mountAct->setData(QVariant(MOUNT_ID)); bool enable = !(mountMan->nonmountFilesystem(system->type(), system->mntPoint())); mountAct->setEnabled(enable); } else { QAction * umountAct = popup.addAction(i18n("Unmount")); umountAct->setData(QVariant(UNMOUNT_ID)); bool enable = !(mountMan->nonmountFilesystem(system->type(), system->mntPoint())); umountAct->setEnabled(enable); } if (mountMan->ejectable(system->mntPoint())) // if (system->type()=="iso9660" || mountMan->followLink(system->name()).left(2)=="cd") popup.addAction(i18n("Eject"))->setData(QVariant(EJECT_ID)); else { QAction *formatAct = popup.addAction(i18n("Format")); formatAct->setData(QVariant(FORMAT_ID)); formatAct->setEnabled(false); } QString mountPoint = system->mntPoint(); QAction * res = popup.exec(pos); int result = -1; if (res && res->data().canConvert()) result = res->data().toInt(); // check out the user's option switch (result) { case - 1 : return ; // the user clicked outside of the menu case MOUNT_ID : case UNMOUNT_ID : mountMan->toggleMount(mountPoint); break; case FORMAT_ID : break; case EJECT_ID : mountMan->eject(mountPoint); break; } } void KMountManGUI::slotToggleMount() { QTreeWidgetItem *item = mountList->currentItem(); if(item) { mountMan->toggleMount(getFsData(item)->mntPoint()); } } void KMountManGUI::slotEject() { QTreeWidgetItem *item = mountList->currentItem(); if(item) { mountMan->eject(getFsData(item)->mntPoint()); } } fsData* KMountManGUI::getFsData(QTreeWidgetItem *item) { for (QList::Iterator it = fileSystems.begin(); it != fileSystems.end(); ++it) { // the only thing which is unique is the mount point if ((*it).mntPoint() == getMntPoint(item)) { return & (*it); } } //this point shouldn't be reached abort(); return 0; } QString KMountManGUI::getMntPoint(QTreeWidgetItem *item) { return item->text(2); // text(2) ? ugly ugly ugly } KrMountDetector::KrMountDetector() { hasMountsChanged(); } bool KrMountDetector::hasMountsChanged() { bool result = false; #ifndef BSD QFileInfo mtabInfo(MTAB); if (!mtabInfo.exists() || mtabInfo.isSymLink()) { // if mtab is a symlimk to /proc/mounts the mtime is unusable #endif KMountPoint::List mountPoints = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName); QCryptographicHash md5(QCryptographicHash::Md5); for (KMountPoint::List::iterator i = mountPoints.begin(); i != mountPoints.end(); ++i) { md5.addData((*i)->mountedFrom().toUtf8()); md5.addData((*i)->realDeviceName().toUtf8()); md5.addData((*i)->mountPoint().toUtf8()); md5.addData((*i)->mountType().toUtf8()); } QString s = md5.result(); result = s != checksum; checksum = s; #ifndef BSD } else { result = mtabInfo.lastModified() != lastMtab; lastMtab = mtabInfo.lastModified(); } #endif return result; } KrMountDetector krMountDetector; KrMountDetector * KrMountDetector::getInstance() { return & krMountDetector; } diff --git a/krusader/MountMan/kmountmangui.h b/krusader/MountMan/kmountmangui.h index a243ef0c..573b1f07 100644 --- a/krusader/MountMan/kmountmangui.h +++ b/krusader/MountMan/kmountmangui.h @@ -1,201 +1,203 @@ /*************************************************************************** kmountmangui.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KMOUNTMANGUI_H #define KMOUNTMANGUI_H -#include -#include -#include -#include -#include +// QtCore +#include +#include +#include +// QtWidgets +#include +#include #include #include "../GUI/krtreewidget.h" #include "kmountman.h" #define WATCHER_DELAY 500 class QCheckBox; class KRFSDisplay; // forward definitions class fsData; class KMountManGUI : public QDialog { Q_OBJECT enum Pages { Filesystems = 0 }; public: KMountManGUI(KMountMan *mntMan); ~KMountManGUI(); protected: virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; protected slots: void doubleClicked(QTreeWidgetItem *); void clicked(QTreeWidgetItem *, const QPoint &); void slotToggleMount(); void slotEject(); void changeActive(); void changeActive(QTreeWidgetItem *); void checkMountChange(); // check whether the mount table was changed void updateList(); // fill-up the filesystems list void getSpaceData(); protected: QLayout *createMainPage(); // creator of the main page - filesystems void addItemToMountList(KrTreeWidget *lst, fsData &fs); fsData* getFsData(QTreeWidgetItem *item); QString getMntPoint(QTreeWidgetItem *item); void addNonMounted(); private: KMountMan *mountMan; KRFSDisplay *info; KrTreeWidget *mountList; QCheckBox *cbShowOnlyRemovable; QPushButton *mountButton; QPushButton *ejectButton; QTimer *watcher; QDateTime lastMtab; // used for the getSpace - gotSpace functions KMountPoint::List possible, mounted; QList fileSystems; int sizeX; int sizeY; }; // Data container for a single-filesystem data // maximum size supported is 2GB of 1kb blocks == 2048GB, enough. // not really needed, but kept for backward compatibility class fsData { public: fsData() : Name(), Type(), MntPoint(), TotalBlks(0), FreeBlks(0), Mounted(false) {} // get information inline QString name() { return Name; } inline QString shortName() { return Name.right(Name.length() - Name.indexOf("/", 1) - 1); } inline QString type() { return Type; } inline QString mntPoint() { return MntPoint; } inline long totalBlks() { return TotalBlks; } inline long freeBlks() { return FreeBlks; } inline KIO::filesize_t totalBytes() { return TotalBlks * 1024; } inline KIO::filesize_t freeBytes() { return FreeBlks * 1024; } //////////////////// insert a good round function here ///////////////// int usedPerct() { if (TotalBlks == 0) return 0; float res = ((float)(TotalBlks - FreeBlks)) / ((float) TotalBlks) * 100; if ((res - (int) res) > 0.5) return (int) res + 1; else return (int) res; } inline bool mounted() { return Mounted; } // set information inline void setName(QString n_) { Name = n_; } inline void setType(QString t_) { Type = t_; } inline void setMntPoint(QString m_) { MntPoint = m_; } inline void setTotalBlks(long t_) { TotalBlks = t_; } inline void setFreeBlks(long f_) { FreeBlks = f_; } inline void setMounted(bool m_) { Mounted = m_; } private: QString Name; // i.e: /dev/cdrom QString Type; // i.e: iso9600 QString MntPoint; // i.e: /mnt/cdrom long TotalBlks; // measured in 1024bytes per block long FreeBlks; bool Mounted; // true if filesystem is mounted // additional attributes of a filesystem, parsed from fstab public: QString options; // additional fstab options }; class KrMountDetector { QString checksum; #ifndef BSD QDateTime lastMtab; #endif public: KrMountDetector(); static KrMountDetector * getInstance(); bool hasMountsChanged(); }; #endif