Add "Eject" button to main window.
Since especially Windows puts the eject functionality behind an icon in the systray which is usually hidden and doesn't complain if a USB drive is unplugged without ejecting it first ejecting such a device might not be obvious to everyone. Add a button to the main window allowing to eject the selected player. Currently only implemented for Windows. Change-Id: I785ac1482cda03a1379cf6d0fd0d9a0ff8130092
This commit is contained in:
parent
4f99dd4264
commit
328ff6d979
7 changed files with 137 additions and 29 deletions
|
@ -692,3 +692,63 @@ QStringList Utils::findRunningProcess(QStringList names)
|
|||
qDebug() << "[Utils] Found listed processes running:" << found;
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/** Eject device from PC.
|
||||
* Request the OS to eject the player.
|
||||
* @param device mountpoint of the device
|
||||
* @return true on success, fals otherwise.
|
||||
*/
|
||||
bool Utils::ejectDevice(QString device)
|
||||
{
|
||||
#if defined(Q_OS_WIN32)
|
||||
/* See http://support.microsoft.com/kb/165721 on the procedure to eject a
|
||||
* device. */
|
||||
bool success = false;
|
||||
int i;
|
||||
HANDLE hdl;
|
||||
DWORD bytesReturned;
|
||||
TCHAR volume[8];
|
||||
|
||||
/* CreateFile */
|
||||
_stprintf(volume, _TEXT("\\\\.\\%c:"), device.toAscii().at(0));
|
||||
hdl = CreateFile(volume, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
if(hdl == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
/* lock volume to make sure no other application is accessing the volume.
|
||||
* Try up to 10 times. */
|
||||
for(i = 0; i < 10; i++) {
|
||||
if(DeviceIoControl(hdl, FSCTL_LOCK_VOLUME,
|
||||
NULL, 0, NULL, 0, &bytesReturned, NULL))
|
||||
break;
|
||||
/* short break before retry */
|
||||
Sleep(100);
|
||||
}
|
||||
if(i < 10) {
|
||||
/* successfully locked, now dismount */
|
||||
if(DeviceIoControl(hdl, FSCTL_DISMOUNT_VOLUME,
|
||||
NULL, 0, NULL, 0, &bytesReturned, NULL)) {
|
||||
/* make sure media can be removed. */
|
||||
PREVENT_MEDIA_REMOVAL pmr;
|
||||
pmr.PreventMediaRemoval = false;
|
||||
if(DeviceIoControl(hdl, IOCTL_STORAGE_MEDIA_REMOVAL,
|
||||
&pmr, sizeof(PREVENT_MEDIA_REMOVAL),
|
||||
NULL, 0, &bytesReturned, NULL)) {
|
||||
/* eject the media */
|
||||
if(DeviceIoControl(hdl, IOCTL_STORAGE_EJECT_MEDIA,
|
||||
NULL, 0, NULL, 0, &bytesReturned, NULL))
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* close handle */
|
||||
CloseHandle(hdl);
|
||||
return success;
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
static QString resolveDevicename(QString path);
|
||||
static QString resolveMountPoint(QString device);
|
||||
static QStringList findRunningProcess(QStringList names);
|
||||
static bool ejectDevice(QString device);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
BIN
rbutil/rbutilqt/icons/media-eject.png
Normal file
BIN
rbutil/rbutilqt/icons/media-eject.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
|
@ -110,6 +110,11 @@ RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
|
|||
RegCloseKey(hk);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(Q_OS_WIN32)
|
||||
/* eject funtionality is only implemented on W32 right now. */
|
||||
ui.buttonEject->setEnabled(false);
|
||||
#endif
|
||||
updateDevice();
|
||||
downloadInfo();
|
||||
|
||||
|
@ -142,6 +147,7 @@ RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
|
|||
connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog()));
|
||||
connect(ui.actionE_xit, SIGNAL(triggered()), this, SLOT(shutdown()));
|
||||
connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog()));
|
||||
connect(ui.buttonEject, SIGNAL(clicked()), this, SLOT(eject()));
|
||||
connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
|
||||
connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
|
||||
connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice()));
|
||||
|
@ -733,3 +739,19 @@ void RbUtilQt::changeEvent(QEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
void RbUtilQt::eject(void)
|
||||
{
|
||||
QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
|
||||
if(Utils::ejectDevice(mountpoint)) {
|
||||
QMessageBox::information(this, tr("Device ejected"),
|
||||
tr("Device successfully ejected. "
|
||||
"You may now disconnect the player from the PC."));
|
||||
}
|
||||
else {
|
||||
QMessageBox::critical(this, tr("Ejecting failed"),
|
||||
tr("Ejecting the device failed. Please make sure no programs "
|
||||
"are accessing files on the device. If ejecting still "
|
||||
"fails please use your computers eject funtionality."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ class RbUtilQt : public QMainWindow
|
|||
void help(void);
|
||||
void sysinfo(void);
|
||||
void trace(void);
|
||||
void eject(void);
|
||||
void configDialog(void);
|
||||
void updateDevice(void);
|
||||
void updateSettings(void);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<file>icons/edit-find.png</file>
|
||||
<file>icons/font_btn.png</file>
|
||||
<file>icons/go-next.png</file>
|
||||
<file>icons/media-eject.png</file>
|
||||
<file>icons/network-idle.png</file>
|
||||
<file>icons/package-x-generic.png</file>
|
||||
<file>icons/preferences-desktop-locale.png</file>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>650</width>
|
||||
<height>550</height>
|
||||
<height>399</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -31,24 +31,25 @@
|
|||
<string>Device</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelMountpoint">
|
||||
<property name="text">
|
||||
<string>mountpoint unknown or invalid</string>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<widget class="QLabel" name="labelPlayerPic">
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelMountpointTitle">
|
||||
<property name="text">
|
||||
<string>Mountpoint:</string>
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelDevice">
|
||||
<property name="text">
|
||||
<string>device unknown or invalid</string>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="rbutilqt.qrc">:/icons/rockbox-32.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -65,6 +66,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelDevice">
|
||||
<property name="text">
|
||||
<string>device unknown or invalid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -78,17 +86,7 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="labelPlayerPic">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" rowspan="2">
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="buttonChangeDevice">
|
||||
<property name="text">
|
||||
<string>&Change</string>
|
||||
|
@ -99,6 +97,31 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4" rowspan="2">
|
||||
<widget class="QPushButton" name="buttonEject">
|
||||
<property name="text">
|
||||
<string>&Eject</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="rbutilqt.qrc">
|
||||
<normaloff>:/icons/media-eject.png</normaloff>:/icons/media-eject.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="labelMountpointTitle">
|
||||
<property name="text">
|
||||
<string>Mountpoint:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelMountpoint">
|
||||
<property name="text">
|
||||
<string>mountpoint unknown or invalid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -130,7 +153,7 @@
|
|||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>7</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="selective">
|
||||
<attribute name="title">
|
||||
|
@ -388,7 +411,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>650</width>
|
||||
<height>23</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
|
|
Loading…
Reference in a new issue