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 /rbutil | |
parent | 4f99dd4264f9aaaccbf3da6bba37d5b2c7eb6f32 (diff) | |
download | rockbox-328ff6d979c028ecba9c57d12c1e75637be20396.tar.gz rockbox-328ff6d979c028ecba9c57d12c1e75637be20396.zip |
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
Diffstat (limited to 'rbutil')
-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 3821b67201..cffa4b1cad 100644 --- a/rbutil/rbutilqt/base/utils.cpp +++ b/rbutil/rbutilqt/base/utils.cpp | |||
@@ -692,3 +692,63 @@ QStringList Utils::findRunningProcess(QStringList names) | |||
692 | qDebug() << "[Utils] Found listed processes running:" << found; | 692 | qDebug() << "[Utils] Found listed processes running:" << found; |
693 | return found; | 693 | return found; |
694 | } | 694 | } |
695 | |||
696 | |||
697 | /** Eject device from PC. | ||
698 | * Request the OS to eject the player. | ||
699 | * @param device mountpoint of the device | ||
700 | * @return true on success, fals otherwise. | ||
701 | */ | ||
702 | bool Utils::ejectDevice(QString device) | ||
703 | { | ||
704 | #if defined(Q_OS_WIN32) | ||
705 | /* See http://support.microsoft.com/kb/165721 on the procedure to eject a | ||
706 | * device. */ | ||
707 | bool success = false; | ||
708 | int i; | ||
709 | HANDLE hdl; | ||
710 | DWORD bytesReturned; | ||
711 | TCHAR volume[8]; | ||
712 | |||
713 | /* CreateFile */ | ||
714 | _stprintf(volume, _TEXT("\\\\.\\%c:"), device.toAscii().at(0)); | ||
715 | hdl = CreateFile(volume, GENERIC_READ | GENERIC_WRITE, | ||
716 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | ||
717 | OPEN_EXISTING, 0, NULL); | ||
718 | if(hdl == INVALID_HANDLE_VALUE) | ||
719 | return false; | ||
720 | |||
721 | /* lock volume to make sure no other application is accessing the volume. | ||
722 | * Try up to 10 times. */ | ||
723 | for(i = 0; i < 10; i++) { | ||
724 | if(DeviceIoControl(hdl, FSCTL_LOCK_VOLUME, | ||
725 | NULL, 0, NULL, 0, &bytesReturned, NULL)) | ||
726 | break; | ||
727 | /* short break before retry */ | ||
728 | Sleep(100); | ||
729 | } | ||
730 | if(i < 10) { | ||
731 | /* successfully locked, now dismount */ | ||
732 | if(DeviceIoControl(hdl, FSCTL_DISMOUNT_VOLUME, | ||
733 | NULL, 0, NULL, 0, &bytesReturned, NULL)) { | ||
734 | /* make sure media can be removed. */ | ||
735 | PREVENT_MEDIA_REMOVAL pmr; | ||
736 | pmr.PreventMediaRemoval = false; | ||
737 | if(DeviceIoControl(hdl, IOCTL_STORAGE_MEDIA_REMOVAL, | ||
738 | &pmr, sizeof(PREVENT_MEDIA_REMOVAL), | ||
739 | NULL, 0, &bytesReturned, NULL)) { | ||
740 | /* eject the media */ | ||
741 | if(DeviceIoControl(hdl, IOCTL_STORAGE_EJECT_MEDIA, | ||
742 | NULL, 0, NULL, 0, &bytesReturned, NULL)) | ||
743 | success = true; | ||
744 | } | ||
745 | } | ||
746 | } | ||
747 | /* close handle */ | ||
748 | CloseHandle(hdl); | ||
749 | return success; | ||
750 | |||
751 | #endif | ||
752 | return false; | ||
753 | } | ||
754 | |||
diff --git a/rbutil/rbutilqt/base/utils.h b/rbutil/rbutilqt/base/utils.h index 185c0323a6..db52bfb4e9 100644 --- a/rbutil/rbutilqt/base/utils.h +++ b/rbutil/rbutilqt/base/utils.h | |||
@@ -50,6 +50,7 @@ public: | |||
50 | static QString resolveDevicename(QString path); | 50 | static QString resolveDevicename(QString path); |
51 | static QString resolveMountPoint(QString device); | 51 | static QString resolveMountPoint(QString device); |
52 | static QStringList findRunningProcess(QStringList names); | 52 | static QStringList findRunningProcess(QStringList names); |
53 | static bool ejectDevice(QString device); | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | #endif | 56 | #endif |
diff --git a/rbutil/rbutilqt/icons/media-eject.png b/rbutil/rbutilqt/icons/media-eject.png new file mode 100644 index 0000000000..2084067e94 --- /dev/null +++ b/rbutil/rbutilqt/icons/media-eject.png | |||
Binary files differ | |||
diff --git a/rbutil/rbutilqt/rbutilqt.cpp b/rbutil/rbutilqt/rbutilqt.cpp index 62a4f583f7..aa0c365303 100644 --- a/rbutil/rbutilqt/rbutilqt.cpp +++ b/rbutil/rbutilqt/rbutilqt.cpp | |||
@@ -110,6 +110,11 @@ RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent) | |||
110 | RegCloseKey(hk); | 110 | RegCloseKey(hk); |
111 | } | 111 | } |
112 | #endif | 112 | #endif |
113 | |||
114 | #if !defined(Q_OS_WIN32) | ||
115 | /* eject funtionality is only implemented on W32 right now. */ | ||
116 | ui.buttonEject->setEnabled(false); | ||
117 | #endif | ||
113 | updateDevice(); | 118 | updateDevice(); |
114 | downloadInfo(); | 119 | downloadInfo(); |
115 | 120 | ||
@@ -142,6 +147,7 @@ RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent) | |||
142 | connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog())); | 147 | connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog())); |
143 | connect(ui.actionE_xit, SIGNAL(triggered()), this, SLOT(shutdown())); | 148 | connect(ui.actionE_xit, SIGNAL(triggered()), this, SLOT(shutdown())); |
144 | connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog())); | 149 | connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog())); |
150 | connect(ui.buttonEject, SIGNAL(clicked()), this, SLOT(eject())); | ||
145 | connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles())); | 151 | connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles())); |
146 | connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile())); | 152 | connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile())); |
147 | connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice())); | 153 | connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice())); |
@@ -733,3 +739,19 @@ void RbUtilQt::changeEvent(QEvent *e) | |||
733 | } | 739 | } |
734 | } | 740 | } |
735 | 741 | ||
742 | void RbUtilQt::eject(void) | ||
743 | { | ||
744 | QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString(); | ||
745 | if(Utils::ejectDevice(mountpoint)) { | ||
746 | QMessageBox::information(this, tr("Device ejected"), | ||
747 | tr("Device successfully ejected. " | ||
748 | "You may now disconnect the player from the PC.")); | ||
749 | } | ||
750 | else { | ||
751 | QMessageBox::critical(this, tr("Ejecting failed"), | ||
752 | tr("Ejecting the device failed. Please make sure no programs " | ||
753 | "are accessing files on the device. If ejecting still " | ||
754 | "fails please use your computers eject funtionality.")); | ||
755 | } | ||
756 | } | ||
757 | |||
diff --git a/rbutil/rbutilqt/rbutilqt.h b/rbutil/rbutilqt/rbutilqt.h index 1db100430a..350aca1956 100644 --- a/rbutil/rbutilqt/rbutilqt.h +++ b/rbutil/rbutilqt/rbutilqt.h | |||
@@ -79,6 +79,7 @@ class RbUtilQt : public QMainWindow | |||
79 | void help(void); | 79 | void help(void); |
80 | void sysinfo(void); | 80 | void sysinfo(void); |
81 | void trace(void); | 81 | void trace(void); |
82 | void eject(void); | ||
82 | void configDialog(void); | 83 | void configDialog(void); |
83 | void updateDevice(void); | 84 | void updateDevice(void); |
84 | void updateSettings(void); | 85 | void updateSettings(void); |
diff --git a/rbutil/rbutilqt/rbutilqt.qrc b/rbutil/rbutilqt/rbutilqt.qrc index 5305a98434..d1eea6872e 100644 --- a/rbutil/rbutilqt/rbutilqt.qrc +++ b/rbutil/rbutilqt/rbutilqt.qrc | |||
@@ -19,6 +19,7 @@ | |||
19 | <file>icons/edit-find.png</file> | 19 | <file>icons/edit-find.png</file> |
20 | <file>icons/font_btn.png</file> | 20 | <file>icons/font_btn.png</file> |
21 | <file>icons/go-next.png</file> | 21 | <file>icons/go-next.png</file> |
22 | <file>icons/media-eject.png</file> | ||
22 | <file>icons/network-idle.png</file> | 23 | <file>icons/network-idle.png</file> |
23 | <file>icons/package-x-generic.png</file> | 24 | <file>icons/package-x-generic.png</file> |
24 | <file>icons/preferences-desktop-locale.png</file> | 25 | <file>icons/preferences-desktop-locale.png</file> |
diff --git a/rbutil/rbutilqt/rbutilqtfrm.ui b/rbutil/rbutilqt/rbutilqtfrm.ui index 85da42ed01..65348dabfb 100644 --- a/rbutil/rbutilqt/rbutilqtfrm.ui +++ b/rbutil/rbutilqt/rbutilqtfrm.ui | |||
@@ -7,7 +7,7 @@ | |||
7 | <x>0</x> | 7 | <x>0</x> |
8 | <y>0</y> | 8 | <y>0</y> |
9 | <width>650</width> | 9 | <width>650</width> |
10 | <height>550</height> | 10 | <height>399</height> |
11 | </rect> | 11 | </rect> |
12 | </property> | 12 | </property> |
13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
@@ -31,24 +31,25 @@ | |||
31 | <string>Device</string> | 31 | <string>Device</string> |
32 | </property> | 32 | </property> |
33 | <layout class="QGridLayout" name="gridLayout"> | 33 | <layout class="QGridLayout" name="gridLayout"> |
34 | <item row="1" column="2"> | 34 | <item row="0" column="0" rowspan="3"> |
35 | <widget class="QLabel" name="labelMountpoint"> | 35 | <widget class="QLabel" name="labelPlayerPic"> |
36 | <property name="text"> | 36 | <property name="lineWidth"> |
37 | <string>mountpoint unknown or invalid</string> | 37 | <number>1</number> |
38 | </property> | 38 | </property> |
39 | </widget> | ||
40 | </item> | ||
41 | <item row="1" column="1"> | ||
42 | <widget class="QLabel" name="labelMountpointTitle"> | ||
43 | <property name="text"> | 39 | <property name="text"> |
44 | <string>Mountpoint:</string> | 40 | <string/> |
45 | </property> | 41 | </property> |
46 | </widget> | 42 | <property name="pixmap"> |
47 | </item> | 43 | <pixmap resource="rbutilqt.qrc">:/icons/rockbox-32.png</pixmap> |
48 | <item row="0" column="2"> | 44 | </property> |
49 | <widget class="QLabel" name="labelDevice"> | 45 | <property name="scaledContents"> |
50 | <property name="text"> | 46 | <bool>false</bool> |
51 | <string>device unknown or invalid</string> | 47 | </property> |
48 | <property name="alignment"> | ||
49 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | ||
50 | </property> | ||
51 | <property name="margin"> | ||
52 | <number>3</number> | ||
52 | </property> | 53 | </property> |
53 | </widget> | 54 | </widget> |
54 | </item> | 55 | </item> |
@@ -65,6 +66,13 @@ | |||
65 | </property> | 66 | </property> |
66 | </widget> | 67 | </widget> |
67 | </item> | 68 | </item> |
69 | <item row="0" column="2"> | ||
70 | <widget class="QLabel" name="labelDevice"> | ||
71 | <property name="text"> | ||
72 | <string>device unknown or invalid</string> | ||
73 | </property> | ||
74 | </widget> | ||
75 | </item> | ||
68 | <item row="0" column="3"> | 76 | <item row="0" column="3"> |
69 | <spacer name="horizontalSpacer"> | 77 | <spacer name="horizontalSpacer"> |
70 | <property name="orientation"> | 78 | <property name="orientation"> |
@@ -78,24 +86,39 @@ | |||
78 | </property> | 86 | </property> |
79 | </spacer> | 87 | </spacer> |
80 | </item> | 88 | </item> |
81 | <item row="0" column="0" rowspan="2"> | 89 | <item row="0" column="4"> |
82 | <widget class="QLabel" name="labelPlayerPic"> | 90 | <widget class="QPushButton" name="buttonChangeDevice"> |
83 | <property name="text"> | 91 | <property name="text"> |
84 | <string/> | 92 | <string>&Change</string> |
85 | </property> | 93 | </property> |
86 | <property name="scaledContents"> | 94 | <property name="icon"> |
87 | <bool>true</bool> | 95 | <iconset resource="rbutilqt.qrc"> |
96 | <normaloff>:/icons/edit-find.png</normaloff>:/icons/edit-find.png</iconset> | ||
88 | </property> | 97 | </property> |
89 | </widget> | 98 | </widget> |
90 | </item> | 99 | </item> |
91 | <item row="0" column="4" rowspan="2"> | 100 | <item row="1" column="4" rowspan="2"> |
92 | <widget class="QPushButton" name="buttonChangeDevice"> | 101 | <widget class="QPushButton" name="buttonEject"> |
93 | <property name="text"> | 102 | <property name="text"> |
94 | <string>&Change</string> | 103 | <string>&Eject</string> |
95 | </property> | 104 | </property> |
96 | <property name="icon"> | 105 | <property name="icon"> |
97 | <iconset resource="rbutilqt.qrc"> | 106 | <iconset resource="rbutilqt.qrc"> |
98 | <normaloff>:/icons/edit-find.png</normaloff>:/icons/edit-find.png</iconset> | 107 | <normaloff>:/icons/media-eject.png</normaloff>:/icons/media-eject.png</iconset> |
108 | </property> | ||
109 | </widget> | ||
110 | </item> | ||
111 | <item row="1" column="1"> | ||
112 | <widget class="QLabel" name="labelMountpointTitle"> | ||
113 | <property name="text"> | ||
114 | <string>Mountpoint:</string> | ||
115 | </property> | ||
116 | </widget> | ||
117 | </item> | ||
118 | <item row="1" column="2"> | ||
119 | <widget class="QLabel" name="labelMountpoint"> | ||
120 | <property name="text"> | ||
121 | <string>mountpoint unknown or invalid</string> | ||
99 | </property> | 122 | </property> |
100 | </widget> | 123 | </widget> |
101 | </item> | 124 | </item> |
@@ -130,7 +153,7 @@ | |||
130 | <item row="1" column="0" colspan="2"> | 153 | <item row="1" column="0" colspan="2"> |
131 | <widget class="QTabWidget" name="tabWidget"> | 154 | <widget class="QTabWidget" name="tabWidget"> |
132 | <property name="currentIndex"> | 155 | <property name="currentIndex"> |
133 | <number>7</number> | 156 | <number>0</number> |
134 | </property> | 157 | </property> |
135 | <widget class="QWidget" name="selective"> | 158 | <widget class="QWidget" name="selective"> |
136 | <attribute name="title"> | 159 | <attribute name="title"> |
@@ -388,7 +411,7 @@ | |||
388 | <x>0</x> | 411 | <x>0</x> |
389 | <y>0</y> | 412 | <y>0</y> |
390 | <width>650</width> | 413 | <width>650</width> |
391 | <height>23</height> | 414 | <height>21</height> |
392 | </rect> | 415 | </rect> |
393 | </property> | 416 | </property> |
394 | <widget class="QMenu" name="menu_File"> | 417 | <widget class="QMenu" name="menu_File"> |