From 4c44d87c732a9bd2e2b02278ebd287cd57376a50 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 29 Aug 2012 14:35:32 -0500 Subject: [PATCH] Fix TDEHW library media backend Add PictBridge camera support to same --- kcontrol/hwmanager/devicepropsdlg.cpp | 79 ++++- kcontrol/hwmanager/devicepropsdlg.h | 3 + kcontrol/hwmanager/devicepropsdlgbase.ui | 57 +++- .../media/mediamanager/tdehardwarebackend.cpp | 311 ++++++++++++++++-- .../media/mediamanager/tdehardwarebackend.h | 2 + 5 files changed, 418 insertions(+), 34 deletions(-) diff --git a/kcontrol/hwmanager/devicepropsdlg.cpp b/kcontrol/hwmanager/devicepropsdlg.cpp index 784c49b69..ee5ee5981 100644 --- a/kcontrol/hwmanager/devicepropsdlg.cpp +++ b/kcontrol/hwmanager/devicepropsdlg.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "devicepropsdlg.h" @@ -286,6 +287,11 @@ DevicePropertiesDialog::DevicePropertiesDialog(TDEGenericDevice* device, TQWidge if (m_device->type() == TDEGenericDeviceType::CPU) { connect(base->comboCPUGovernor, TQT_SIGNAL(activated(const TQString &)), this, TQT_SLOT(setCPUGovernor(const TQString &))); } + if (m_device->type() == TDEGenericDeviceType::Disk) { + connect(base->buttonDiskMount, TQT_SIGNAL(clicked()), this, TQT_SLOT(mountDisk())); + connect(base->buttonDiskUnmount, TQT_SIGNAL(clicked()), this, TQT_SLOT(unmountDisk())); + } + if ((m_device->type() == TDEGenericDeviceType::OtherSensor) || (m_device->type() == TDEGenericDeviceType::ThermalSensor)) { base->groupSensors->setColumnLayout(0, TQt::Vertical ); base->groupSensors->layout()->setSpacing( KDialog::spacingHint() ); @@ -370,7 +376,18 @@ void DevicePropertiesDialog::populateDeviceInformation() { if (m_device->type() == TDEGenericDeviceType::Disk) { TDEStorageDevice* sdevice = static_cast(m_device); - base->labelDiskMountpoint->setText(sdevice->mountPath()); + + TQString mountPoint = sdevice->mountPath(); + if (mountPoint == "") mountPoint = i18n(""); + base->labelDiskMountpoint->setText(mountPoint); + + TQString fsName = sdevice->fileSystemName(); + if (fsName == "") fsName = i18n(""); + base->labelDiskFileSystemType->setText(fsName); + + TQString volUUID = sdevice->diskUUID(); + if (volUUID == "") volUUID = i18n(""); + base->labelDiskUUID->setText(volUUID); // Show status TQString status_text = ""; @@ -401,8 +418,15 @@ void DevicePropertiesDialog::populateDeviceInformation() { status_text += ""; base->labelDiskStatus->setText(status_text); - // TODO - // Add mount/unmount buttons + // Update mount/unmount button status + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Mountable)) { + base->groupDiskActions->show(); + base->buttonDiskMount->setEnabled((sdevice->mountPath() == "")); + base->buttonDiskUnmount->setEnabled((sdevice->mountPath() != "")); + } + else { + base->groupDiskActions->hide(); + } } if (m_device->type() == TDEGenericDeviceType::CPU) { @@ -742,6 +766,55 @@ void DevicePropertiesDialog::setHibernationMethod(int value) { populateDeviceInformation(); } +void DevicePropertiesDialog::mountDisk() { + TDEStorageDevice* sdevice = static_cast(m_device); + + // FIXME + // This can only mount normal volumes + TQString qerror; + TQString diskLabel = sdevice->diskLabel(); + if (diskLabel.isNull()) { + diskLabel = i18n("%1 Removable Device").arg(sdevice->deviceFriendlySize()); + } + TQString optionString; + TQString mountMessages; + TQString mountedPath = sdevice->mountDevice(diskLabel, optionString, &mountMessages); + if (mountedPath.isNull()) { + qerror = i18n("Unable to mount this device.

Potential reasons include:
Improper device and/or user privilege level
Corrupt data on storage device"); + if (!mountMessages.isNull()) { + qerror.append(i18n("

Technical details:
").append(mountMessages)); + } + qerror.append(""); + } + else { + qerror = ""; + } + + if (qerror != "") KMessageBox::error(this, qerror, i18n("Mount Failed")); + + populateDeviceInformation(); +} + +void DevicePropertiesDialog::unmountDisk() { + TDEStorageDevice* sdevice = static_cast(m_device); + + TQString qerror; + TQString unmountMessages; + int unmountRetcode = 0; + if (!sdevice->unmountDevice(&unmountMessages, &unmountRetcode)) { + // Unmount failed! + qerror = "" + i18n("Unfortunately, the device could not be unmounted."); + if (!unmountMessages.isNull()) { + qerror.append(i18n("

Technical details:
").append(unmountMessages)); + } + qerror.append(""); + } + + if (qerror != "") KMessageBox::error(this, qerror, i18n("Unmount Failed")); + + populateDeviceInformation(); +} + void DevicePropertiesDialog::virtual_hook( int id, void* data ) { KDialogBase::virtual_hook( id, data ); } diff --git a/kcontrol/hwmanager/devicepropsdlg.h b/kcontrol/hwmanager/devicepropsdlg.h index 192ebffd4..bbff43977 100644 --- a/kcontrol/hwmanager/devicepropsdlg.h +++ b/kcontrol/hwmanager/devicepropsdlg.h @@ -188,6 +188,9 @@ private slots: void setBacklightBrightness(int); void setHibernationMethod(int); + void mountDisk(); + void unmountDisk(); + private: TDEGenericDevice* m_device; DevicePropertiesDialogBase* base; diff --git a/kcontrol/hwmanager/devicepropsdlgbase.ui b/kcontrol/hwmanager/devicepropsdlgbase.ui index dc328d643..bd3688402 100644 --- a/kcontrol/hwmanager/devicepropsdlgbase.ui +++ b/kcontrol/hwmanager/devicepropsdlgbase.ui @@ -280,6 +280,32 @@ + + unnamed + + + Filesystem Type: + + + + + labelDiskFileSystemType + + + + + unnamed + + + Volume UUID: + + + + + labelDiskUUID + + + unnamed @@ -290,13 +316,42 @@ AlignTop|AlignLeft - + labelDiskStatus + + + groupDiskActions + + + Device Actions + + + + unnamed + + + + buttonDiskMount + + + Mount + + + + + buttonDiskUnmount + + + Unmount + + + + Spacer4 diff --git a/kioslave/media/mediamanager/tdehardwarebackend.cpp b/kioslave/media/mediamanager/tdehardwarebackend.cpp index d23e38f32..b24322ef3 100644 --- a/kioslave/media/mediamanager/tdehardwarebackend.cpp +++ b/kioslave/media/mediamanager/tdehardwarebackend.cpp @@ -36,15 +36,25 @@ #include "dialog.h" -#define MOUNT_SUFFIX ( \ - (medium->isMounted() ? TQString("_mounted") : TQString("_unmounted")) + \ - (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypted" : "_encrypted") : "" ) \ +#define MOUNT_SUFFIX ( \ + (medium->isMounted() ? TQString("_mounted") : TQString("_unmounted")) + \ + (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypted" : "_encrypted") : "" ) \ ) -#define MOUNT_ICON_SUFFIX ( \ - (medium->isMounted() ? TQString("_mount") : TQString("_unmount")) + \ - (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypt" : "_encrypt") : "" ) \ +#define MOUNT_ICON_SUFFIX ( \ + (medium->isMounted() ? TQString("_mount") : TQString("_unmount")) + \ + (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypt" : "_encrypt") : "" ) \ ) +#define CHECK_FOR_AND_EXECUTE_AUTOMOUNT(udi, medium, allowNotification) { \ + TQMap options = MediaManagerUtils::splitOptions(mountoptions(udi)); \ + kdDebug() << "automount " << options["automount"] << endl; \ + if (options["automount"] == "true" && allowNotification ) { \ + TQString error = mount(medium); \ + if (!error.isEmpty()) \ + kdDebug() << "error " << error << endl; \ + } \ + } + /* Constructor */ TDEBackend::TDEBackend(MediaList &list, TQObject* parent) : TQObject() @@ -157,6 +167,9 @@ void TDEBackend::AddDevice(TDEStorageDevice * sdevice, bool allowNotification) // Insert medium into list m_mediaList.addMedium(medium, allowNotification); + + // Automount if enabled + CHECK_FOR_AND_EXECUTE_AUTOMOUNT(sdevice->uniqueID(), medium, allowNotification) } } @@ -180,6 +193,9 @@ void TDEBackend::AddDevice(TDEStorageDevice * sdevice, bool allowNotification) // Insert medium into list m_mediaList.addMedium(medium, allowNotification); + + // Automount if enabled + CHECK_FOR_AND_EXECUTE_AUTOMOUNT(sdevice->uniqueID(), medium, allowNotification) } // Floppy & zip drives @@ -250,10 +266,7 @@ void TDEBackend::RemoveDevice(TDEStorageDevice * sdevice) void TDEBackend::ModifyDevice(TDEStorageDevice * sdevice) { - bool allowNotification = true; -// if (!sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) { // FIXME Under which conditions would we not want notification? -// allowNotification = false; -// } + bool allowNotification = false; ResetProperties(sdevice, allowNotification); } @@ -595,25 +608,26 @@ void TDEBackend::setCameraProperties(Medium* medium) return; } - /** @todo find name */ - medium->setName("camera"); + TQString cameraName = sdevice->friendlyName(); + cameraName.replace("/", "_"); + medium->setName(cameraName); TQString device = "camera:/"; - // FIXME - // I don't have a PTP camera to develop with - // Getting this working should be fairly easy; you just have to query udev for this information via the /sys/... path returned by sdevice->systemPath() -// if () { -// device.sprintf("camera://%s@[usb:%03d,%03d]/", , , ); -// } + TQStringList devNodeList = TQStringList::split("/", sdevice->deviceNode(), TRUE); + TQString devNode0 = devNodeList[devNodeList.count()-2]; + TQString devNode1 = devNodeList[devNodeList.count()-1]; + + if ((devNode0 != "") && (devNode1 != "")) { + device.sprintf("camera://@[usb:%s,%s]/", devNode0.ascii(), devNode1.ascii()); + } - /** @todo find the rest of this URL */ medium->unmountableState(device); medium->setMimeType("media/gphoto2camera"); medium->setIconName(TQString::null); - if (sdevice->vendorModel() != "") { - medium->setLabel(sdevice->vendorModel()); + if (sdevice->friendlyName() != "") { + medium->setLabel(sdevice->friendlyName()); } else { medium->setLabel(i18n("Camera")); @@ -648,21 +662,237 @@ TQStringList TDEBackend::mountoptions(const TQString &name) return TQStringList(); // device is listed in fstab, therefore is not handled by us } - TQString volume_udi = name; if (medium->isEncrypted()) { // if not decrypted yet then there are no mountoptions return TQStringList(); } + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id()); + if (!sdevice) { + return TQStringList(); // we can't get the information needed in order to process mount options + } + + TQStringList result; + + // Allow only those options which are valid for the given device + // pmount only allows a subset of options, and those are given in the map below // FIXME - // Just use the default mount options for now - return TQStringList(); + TQMap valids; + valids["ro"] = true; + //valids["quiet"] = false; + //valids["flush"] = false; + //valids["uid"] = false; + valids["utf8"] = true; + //valids["shortname"] = false; + valids["locale"] = true; + valids["sync"] = true; + valids["noatime"] = true; + //valids["data"] = false; + + TQString drive_udi = driveUDIFromDeviceUID(medium->id()); + + KConfig config("mediamanagerrc"); + + bool use_defaults = true; + if (config.hasGroup(drive_udi)) { + config.setGroup(drive_udi); + use_defaults = config.readBoolEntry("use_defaults", false); + } + if (use_defaults) { + config.setGroup("DefaultOptions"); + } + result << TQString("use_defaults=%1").arg(use_defaults ? "true" : "false"); + + bool removable = false; + if (!drive_udi.isNull()) { + removable = ((sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) || (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable))); + } + + TQString tmp; + bool value; + if (use_defaults) { + value = config.readBoolEntry("automount", false); + } + else { + QString current_group = config.group(); + config.setGroup(drive_udi); + value = config.readBoolEntry("automount", false); + config.setGroup(current_group); + } + + if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo)) + ) { + value = false; + } + + result << TQString("automount=%1").arg(value ? "true" : "false"); + + if (valids.contains("ro")) { + value = config.readBoolEntry("ro", false); + tmp = TQString("ro=%1").arg(value ? "true" : "false"); + if (sdevice->fileSystemName() != "iso9660") { + result << tmp; + } + } + + if (valids.contains("quiet")) { + value = config.readBoolEntry("quiet", false); + tmp = TQString("quiet=%1").arg(value ? "true" : "false"); + if (sdevice->fileSystemName() != "iso9660") { + result << tmp; + } + } + + if (valids.contains("flush")) { + value = config.readBoolEntry("flush", sdevice->fileSystemName().endsWith("fat")); + tmp = TQString("flush=%1").arg(value ? "true" : "false"); + result << tmp; + } + + if (valids.contains("uid")) { + value = config.readBoolEntry("uid", true); + tmp = TQString("uid=%1").arg(value ? "true" : "false"); + result << tmp; + } + + if (valids.contains("utf8")) { + value = config.readBoolEntry("utf8", true); + tmp = TQString("utf8=%1").arg(value ? "true" : "false"); + result << tmp; + } + + if (valids.contains("shortname")) { + TQString svalue = config.readEntry("shortname", "lower").lower(); + if (svalue == "winnt") { + result << "shortname=winnt"; + } + else if (svalue == "win95") { + result << "shortname=win95"; + } + else if (svalue == "mixed") { + result << "shortname=mixed"; + } + else { + result << "shortname=lower"; + } + } + + // pass our locale to the ntfs-3g driver so it can translate local characters + if (valids.contains("locale") && (sdevice->fileSystemName() == "ntfs-3g")) { + // have to obtain LC_CTYPE as returned by the `locale` command + // check in the same order as `locale` does + char *cType; + if ( (cType = getenv("LC_ALL")) || (cType = getenv("LC_CTYPE")) || (cType = getenv("LANG")) ) { + result << TQString("locale=%1").arg(cType); + } + } + + if (valids.contains("sync")) { + value = config.readBoolEntry("sync", ( valids.contains("flush") && !sdevice->fileSystemName().endsWith("fat") ) && removable); + tmp = TQString("sync=%1").arg(value ? "true" : "false"); + if (sdevice->fileSystemName() != "iso9660") { + result << tmp; + } + } + + if (valids.contains("noatime")) { + value = config.readBoolEntry("atime", !sdevice->fileSystemName().endsWith("fat")); + tmp = TQString("atime=%1").arg(value ? "true" : "false"); + if (sdevice->fileSystemName() != "iso9660") { + result << tmp; + } + } + + TQString mount_point; + mount_point = config.readEntry("mountpoint", TQString::null); + + if (!mount_point.startsWith("/")) { + mount_point = "/media/" + mount_point; + } + if (mount_point != "") { + result << TQString("mountpoint=%1").arg(mount_point); + } + + TQString file_system_name; + file_system_name = sdevice->fileSystemName(); + if (file_system_name != "") { + result << TQString("filesystem=%1").arg(file_system_name); + } + + if (valids.contains("data")) { + TQString svalue = config.readEntry("journaling").lower(); + if (svalue == "ordered") { + result << "journaling=ordered"; + } + else if (svalue == "writeback") { + result << "journaling=writeback"; + } + else if (svalue == "data") { + result << "journaling=data"; + } + else { + result << "journaling=ordered"; + } + } + + return result; } bool TDEBackend::setMountoptions(const TQString &name, const TQStringList &options ) { - // FIXME - // Just use the default mount options for now + const Medium* medium = m_mediaList.findById(name); + if (!medium) { + return false; // we know nothing about that device + } + if (!isInFstab(medium).isNull()) { + return false; // device is listed in fstab, therefore is not handled by us + } + + TQString drive_udi = driveUDIFromDeviceUID(medium->id()); + + kdDebug() << "setMountoptions " << name << " " << options << endl; + + KConfig config("mediamanagerrc"); + config.setGroup(drive_udi); + + TQMap valids = MediaManagerUtils::splitOptions(options); + + const char *names[] = { "use_defaults", "ro", "quiet", "atime", "uid", "utf8", "flush", "sync", 0 }; + for (int index = 0; names[index]; ++index) { + if (valids.contains(names[index])) { + config.writeEntry(names[index], valids[names[index]] == "true"); + } + } + + if (valids.contains("shortname")) { + config.writeEntry("shortname", valids["shortname"]); + } + + if (valids.contains("journaling")) { + config.writeEntry("journaling", valids["journaling"]); + } + + if (!mountoptions(name).contains(TQString("mountpoint=%1").arg(valids["mountpoint"]))) { + config.writeEntry("mountpoint", valids["mountpoint"]); + } + + if (valids.contains("automount")) { + config.setGroup(drive_udi); + config.writeEntry("automount", valids["automount"]); + } + return true; } @@ -731,11 +961,15 @@ TQString TDEBackend::mount(const Medium *medium) TQString mount_point = valids["mountpoint"]; if (mount_point.startsWith("/media/")) { - mount_point = mount_point.mid(7); + diskLabel = mount_point.mid(7); } - - if (valids.contains("shortname")) { - diskLabel = TQString("shortname=%1").arg(valids["shortname"]); + + if (valids.contains("filesystem")) { + optionString.append(TQString(" -t %1").arg(valids["filesystem"])); + } + + if (valids.contains("locale")) { + optionString.append(TQString(" -c %1").arg(valids["locale"])); } TQString qerror = i18n("Cannot mount encrypted drives!"); @@ -1073,4 +1307,21 @@ TQString TDEBackend::generateName(const TQString &devNode) { return KURL(devNode).fileName(); } + +TQString TDEBackend::driveUDIFromDeviceUID(TQString uuid) { + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(uuid); + TQString ret; + if (sdevice) { + ret = sdevice->diskUUID(); + } + if (ret == "") { + return TQString::null; + } + else { + return ret; + } +} + #include "tdehardwarebackend.moc" \ No newline at end of file diff --git a/kioslave/media/mediamanager/tdehardwarebackend.h b/kioslave/media/mediamanager/tdehardwarebackend.h index b497e48d2..190d06e41 100644 --- a/kioslave/media/mediamanager/tdehardwarebackend.h +++ b/kioslave/media/mediamanager/tdehardwarebackend.h @@ -135,6 +135,8 @@ private: static TQString listUsingProcesses(const Medium *medium); static TQString killUsingProcesses(const Medium *medium); + TQString driveUDIFromDeviceUID(TQString uuid); + // Decryption Dialog* m_decryptDialog; TQString m_decryptionPassword;