diff options
| author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2012-09-08 20:34:36 +0200 |
|---|---|---|
| committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2012-09-08 20:34:36 +0200 |
| commit | 328ff6d979c028ecba9c57d12c1e75637be20396 (patch) | |
| tree | 1373b766c7a1b0a6551816f105ee7447c0f602ae | |
| parent | 4f99dd4264f9aaaccbf3da6bba37d5b2c7eb6f32 (diff) | |
| download | rockbox-328ff6d979c028ecba9c57d12c1e75637be20396.zip rockbox-328ff6d979c028ecba9c57d12c1e75637be20396.tar.gz rockbox-328ff6d979c028ecba9c57d12c1e75637be20396.tar.bz2 rockbox-328ff6d979c028ecba9c57d12c1e75637be20396.tar.xz | |
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
| -rw-r--r-- | rbutil/rbutilqt/base/utils.cpp | 60 | ||||
| -rw-r--r-- | rbutil/rbutilqt/base/utils.h | 1 | ||||
| -rw-r--r-- | rbutil/rbutilqt/icons/media-eject.png | bin | 0 -> 628 bytes | |||
| -rw-r--r-- | rbutil/rbutilqt/rbutilqt.cpp | 22 | ||||
| -rw-r--r-- | rbutil/rbutilqt/rbutilqt.h | 1 | ||||
| -rw-r--r-- | rbutil/rbutilqt/rbutilqt.qrc | 1 | ||||
| -rw-r--r-- | rbutil/rbutilqt/rbutilqtfrm.ui | 77 |
7 files changed, 135 insertions, 27 deletions
diff --git a/rbutil/rbutilqt/base/utils.cpp b/rbutil/rbutilqt/base/utils.cpp index 3821b67..cffa4b1 100644 --- a/rbutil/rbutilqt/base/utils.cpp +++ b/rbutil/rbutilqt/base/utils.cpp @@ -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; +} + diff --git a/rbutil/rbutilqt/base/utils.h b/rbutil/rbutilqt/base/utils.h index 185c032..db52bfb 100644 --- a/rbutil/rbutilqt/base/utils.h +++ b/rbutil/rbutilqt/base/utils.h @@ -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 diff --git a/rbutil/rbutilqt/icons/media-eject.png b/rbutil/rbutilqt/icons/media-eject.png Binary files differnew file mode 100644 index 0000000..2084067 --- /dev/null +++ b/rbutil/rbutilqt/icons/media-eject.png diff --git a/rbutil/rbutilqt/rbutilqt.cpp b/rbutil/rbutilqt/rbutilqt.cpp index 62a4f58..aa0c365 100644 --- a/rbutil/rbutilqt/rbutilqt.cpp +++ b/rbutil/rbutilqt/rbutilqt.cpp @@ -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.")); + } +} + diff --git a/rbutil/rbutilqt/rbutilqt.h b/rbutil/rbutilqt/rbutilqt.h index 1db1004..350aca1 100644 --- a/rbutil/rbutilqt/rbutilqt.h +++ b/rbutil/rbutilqt/rbutilqt.h @@ -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); diff --git a/rbutil/rbutilqt/rbutilqt.qrc b/rbutil/rbutilqt/rbutilqt.qrc index 5305a98..d1eea68 100644 --- a/rbutil/rbutilqt/rbutilqt.qrc +++ b/rbutil/rbutilqt/rbutilqt.qrc @@ -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> diff --git a/rbutil/rbutilqt/rbutilqtfrm.ui b/rbutil/rbutilqt/rbutilqtfrm.ui index 85da42e..65348da 100644 --- a/rbutil/rbutilqt/rbutilqtfrm.ui +++ b/rbutil/rbutilqt/rbutilqtfrm.ui @@ -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,24 +86,39 @@ </property> </spacer> </item> - <item row="0" column="0" rowspan="2"> - <widget class="QLabel" name="labelPlayerPic"> + <item row="0" column="4"> + <widget class="QPushButton" name="buttonChangeDevice"> <property name="text"> - <string/> + <string>&Change</string> </property> - <property name="scaledContents"> - <bool>true</bool> + <property name="icon"> + <iconset resource="rbutilqt.qrc"> + <normaloff>:/icons/edit-find.png</normaloff>:/icons/edit-find.png</iconset> </property> </widget> </item> - <item row="0" column="4" rowspan="2"> - <widget class="QPushButton" name="buttonChangeDevice"> + <item row="1" column="4" rowspan="2"> + <widget class="QPushButton" name="buttonEject"> <property name="text"> - <string>&Change</string> + <string>&Eject</string> </property> <property name="icon"> <iconset resource="rbutilqt.qrc"> - <normaloff>:/icons/edit-find.png</normaloff>:/icons/edit-find.png</iconset> + <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> @@ -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"> |