Merge ~osomon/oxide:contextmenu-copyImage into oxide:master
- Git
- lp:~osomon/oxide
- contextmenu-copyImage
- Merge into master
Proposed by
Olivier Tilloy
Status: | Merged |
---|---|
Merged at revision: | 1776161f8f04b5921020843f899f9eb8e105b8db |
Proposed branch: | ~osomon/oxide:contextmenu-copyImage |
Merge into: | oxide:master |
Diff against target: |
284 lines (+64/-38) 11 files modified
qt/core/browser/clipboard/oxide_qt_clipboard.cc (+4/-27) qt/core/browser/oxide_qt_skutils.cc (+8/-4) qt/core/browser/oxide_qt_web_context_menu.cc (+5/-1) qt/core/browser/oxide_qt_web_context_menu.h (+2/-1) qt/core/glue/oxide_qt_web_context_menu_proxy_client.h (+2/-1) qt/quick/oxide_qquick_web_context_menu.cc (+18/-1) qt/tests/qmltests/api/tst_WebView_contextMenu.qml (+8/-0) qt/tests/qmltests/qml_test_support.cc (+5/-1) qt/tests/qmltests/qml_test_support.h (+2/-0) shared/browser/oxide_web_context_menu.cc (+8/-1) shared/browser/oxide_web_context_menu.h (+2/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Coulson | Approve | ||
Review via email: mp+295690@code.launchpad.net |
Commit message
Add a copyImage() method to the context menu to copy the contents of an image element to the clipboard. Fixes https:/
Description of the change
To post a comment you must log in.
- 9c5022d... by Olivier Tilloy
-
Specify fully-qualified include path.
- e442309... by Olivier Tilloy
-
Detach image instead of copying it.
- 8a323c1... by Olivier Tilloy
-
Call detach() on the returned image in QImageFromSkBit
map(). - d420348... by Olivier Tilloy
-
Re-arrange code for improved readability.
Revision history for this message
Olivier Tilloy (osomon) wrote : | # |
Updated.
Revision history for this message
Chris Coulson (chrisccoulson) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/qt/core/browser/clipboard/oxide_qt_clipboard.cc b/qt/core/browser/clipboard/oxide_qt_clipboard.cc | |||
2 | index d6fd870..38d003e 100644 | |||
3 | --- a/qt/core/browser/clipboard/oxide_qt_clipboard.cc | |||
4 | +++ b/qt/core/browser/clipboard/oxide_qt_clipboard.cc | |||
5 | @@ -1,5 +1,5 @@ | |||
6 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
8 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
9 | 3 | 3 | ||
10 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
11 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
12 | @@ -30,6 +30,8 @@ | |||
13 | 30 | #include <QObject> | 30 | #include <QObject> |
14 | 31 | #include <QString> | 31 | #include <QString> |
15 | 32 | 32 | ||
16 | 33 | #include "qt/core/browser/oxide_qt_skutils.h" | ||
17 | 34 | |||
18 | 33 | #define GET_CLIPBOARD_DATA(c) \ | 35 | #define GET_CLIPBOARD_DATA(c) \ |
19 | 34 | c->mimeData( \ | 36 | c->mimeData( \ |
20 | 35 | type == ui::CLIPBOARD_TYPE_COPY_PASTE ? \ | 37 | type == ui::CLIPBOARD_TYPE_COPY_PASTE ? \ |
21 | @@ -300,32 +302,7 @@ void Clipboard::WriteWebSmartPaste() { | |||
22 | 300 | 302 | ||
23 | 301 | void Clipboard::WriteBitmap(const SkBitmap& bitmap) { | 303 | void Clipboard::WriteBitmap(const SkBitmap& bitmap) { |
24 | 302 | DCHECK(CalledOnValidThread()); | 304 | DCHECK(CalledOnValidThread()); |
51 | 303 | QImage image; | 305 | write_mime_data_acc_->setImageData(QImageFromSkBitmap(bitmap)); |
26 | 304 | if (bitmap.info().colorType() != kN32_SkColorType) { | ||
27 | 305 | SkImageInfo info = | ||
28 | 306 | SkImageInfo::MakeN32(bitmap.width(), | ||
29 | 307 | bitmap.height(), | ||
30 | 308 | bitmap.alphaType()); | ||
31 | 309 | |||
32 | 310 | SkBitmap convertedBitmap; | ||
33 | 311 | if (!convertedBitmap.tryAllocPixels(info)) { | ||
34 | 312 | return; | ||
35 | 313 | } | ||
36 | 314 | |||
37 | 315 | bitmap.readPixels(info, convertedBitmap.getPixels(), 0, 0, 0); | ||
38 | 316 | |||
39 | 317 | image = QImage(reinterpret_cast<const uchar *>(convertedBitmap.getPixels()), | ||
40 | 318 | bitmap.width(), | ||
41 | 319 | bitmap.height(), | ||
42 | 320 | QImage::Format_RGBA8888); | ||
43 | 321 | } else { | ||
44 | 322 | image = QImage(reinterpret_cast<const uchar *>(bitmap.getPixels()), | ||
45 | 323 | bitmap.width(), | ||
46 | 324 | bitmap.height(), | ||
47 | 325 | QImage::Format_RGBA8888); | ||
48 | 326 | } | ||
49 | 327 | |||
50 | 328 | write_mime_data_acc_->setImageData(image.copy()); | ||
52 | 329 | } | 306 | } |
53 | 330 | 307 | ||
54 | 331 | void Clipboard::WriteData(const FormatType& format, | 308 | void Clipboard::WriteData(const FormatType& format, |
55 | diff --git a/qt/core/browser/oxide_qt_skutils.cc b/qt/core/browser/oxide_qt_skutils.cc | |||
56 | index d7bc690..0aecca5 100644 | |||
57 | --- a/qt/core/browser/oxide_qt_skutils.cc | |||
58 | +++ b/qt/core/browser/oxide_qt_skutils.cc | |||
59 | @@ -1,5 +1,5 @@ | |||
60 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
62 | 2 | // Copyright (C) 2014 Canonical Ltd. | 2 | // Copyright (C) 2014-2016 Canonical Ltd. |
63 | 3 | 3 | ||
64 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
65 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
66 | @@ -102,12 +102,16 @@ QImage QImageFromSkBitmap(const SkBitmap& bitmap) { | |||
67 | 102 | QImageFormatFromSkColorType(color, alpha == kPremul_SkAlphaType); | 102 | QImageFormatFromSkColorType(color, alpha == kPremul_SkAlphaType); |
68 | 103 | if (format != QImage::Format_Invalid) { | 103 | if (format != QImage::Format_Invalid) { |
69 | 104 | SkAutoLockPixels lock(bitmap); | 104 | SkAutoLockPixels lock(bitmap); |
72 | 105 | return QImage(reinterpret_cast<const uchar*>(bitmap.getPixels()), | 105 | QImage image(reinterpret_cast<const uchar*>(bitmap.getPixels()), |
73 | 106 | bitmap.width(), bitmap.height(), format); | 106 | bitmap.width(), bitmap.height(), format); |
74 | 107 | image.detach(); | ||
75 | 108 | return image; | ||
76 | 107 | } | 109 | } |
77 | 108 | 110 | ||
78 | 109 | if (color == kBGRA_8888_SkColorType) { | 111 | if (color == kBGRA_8888_SkColorType) { |
80 | 110 | return QImageFromSkBitmap_BGRA_8888(bitmap); | 112 | QImage image = QImageFromSkBitmap_BGRA_8888(bitmap); |
81 | 113 | image.detach(); | ||
82 | 114 | return image; | ||
83 | 111 | } | 115 | } |
84 | 112 | 116 | ||
85 | 113 | LOG(WARNING) << | 117 | LOG(WARNING) << |
86 | diff --git a/qt/core/browser/oxide_qt_web_context_menu.cc b/qt/core/browser/oxide_qt_web_context_menu.cc | |||
87 | index 29202e2..acbbeae 100644 | |||
88 | --- a/qt/core/browser/oxide_qt_web_context_menu.cc | |||
89 | +++ b/qt/core/browser/oxide_qt_web_context_menu.cc | |||
90 | @@ -1,5 +1,5 @@ | |||
91 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
93 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
94 | 3 | 3 | ||
95 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
96 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
97 | @@ -169,6 +169,10 @@ int WebContextMenu::mediaFlags() const { | |||
98 | 169 | return flags; | 169 | return flags; |
99 | 170 | } | 170 | } |
100 | 171 | 171 | ||
101 | 172 | void WebContextMenu::copyImage() const { | ||
102 | 173 | CopyImage(); | ||
103 | 174 | } | ||
104 | 175 | |||
105 | 172 | void WebContextMenu::saveLink() const { | 176 | void WebContextMenu::saveLink() const { |
106 | 173 | SaveLink(); | 177 | SaveLink(); |
107 | 174 | } | 178 | } |
108 | diff --git a/qt/core/browser/oxide_qt_web_context_menu.h b/qt/core/browser/oxide_qt_web_context_menu.h | |||
109 | index 8db72d8..257db2b 100644 | |||
110 | --- a/qt/core/browser/oxide_qt_web_context_menu.h | |||
111 | +++ b/qt/core/browser/oxide_qt_web_context_menu.h | |||
112 | @@ -1,5 +1,5 @@ | |||
113 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
115 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
116 | 3 | 3 | ||
117 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
118 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
119 | @@ -60,6 +60,7 @@ class WebContextMenu : public oxide::WebContextMenu, | |||
120 | 60 | void cancel() override; | 60 | void cancel() override; |
121 | 61 | int editFlags() const override; | 61 | int editFlags() const override; |
122 | 62 | int mediaFlags() const override; | 62 | int mediaFlags() const override; |
123 | 63 | void copyImage() const override; | ||
124 | 63 | void saveLink() const override; | 64 | void saveLink() const override; |
125 | 64 | void saveMedia() const override; | 65 | void saveMedia() const override; |
126 | 65 | 66 | ||
127 | diff --git a/qt/core/glue/oxide_qt_web_context_menu_proxy_client.h b/qt/core/glue/oxide_qt_web_context_menu_proxy_client.h | |||
128 | index b5d0131..123297e 100644 | |||
129 | --- a/qt/core/glue/oxide_qt_web_context_menu_proxy_client.h | |||
130 | +++ b/qt/core/glue/oxide_qt_web_context_menu_proxy_client.h | |||
131 | @@ -1,5 +1,5 @@ | |||
132 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
134 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
135 | 3 | 3 | ||
136 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
137 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
138 | @@ -71,6 +71,7 @@ class WebContextMenuProxyClient { | |||
139 | 71 | 71 | ||
140 | 72 | virtual int mediaFlags() const = 0; | 72 | virtual int mediaFlags() const = 0; |
141 | 73 | 73 | ||
142 | 74 | virtual void copyImage() const = 0; | ||
143 | 74 | virtual void saveLink() const = 0; | 75 | virtual void saveLink() const = 0; |
144 | 75 | virtual void saveMedia() const = 0; | 76 | virtual void saveMedia() const = 0; |
145 | 76 | }; | 77 | }; |
146 | diff --git a/qt/quick/oxide_qquick_web_context_menu.cc b/qt/quick/oxide_qquick_web_context_menu.cc | |||
147 | index 31b4575..561f421 100644 | |||
148 | --- a/qt/quick/oxide_qquick_web_context_menu.cc | |||
149 | +++ b/qt/quick/oxide_qquick_web_context_menu.cc | |||
150 | @@ -1,5 +1,5 @@ | |||
151 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
153 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
154 | 3 | 3 | ||
155 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
156 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
157 | @@ -71,6 +71,7 @@ class ContextMenuContext : public QObject { | |||
158 | 71 | OxideQQuickWebView::EditCapabilities editFlags() const; | 71 | OxideQQuickWebView::EditCapabilities editFlags() const; |
159 | 72 | OxideQQuickWebView::MediaStatus mediaFlags() const; | 72 | OxideQQuickWebView::MediaStatus mediaFlags() const; |
160 | 73 | 73 | ||
161 | 74 | Q_INVOKABLE void copyImage() const; | ||
162 | 74 | Q_INVOKABLE void saveLink() const; | 75 | Q_INVOKABLE void saveLink() const; |
163 | 75 | Q_INVOKABLE void saveMedia() const; | 76 | Q_INVOKABLE void saveMedia() const; |
164 | 76 | 77 | ||
165 | @@ -214,6 +215,22 @@ OxideQQuickWebView::MediaStatus ContextMenuContext::mediaFlags() const { | |||
166 | 214 | return static_cast<OxideQQuickWebView::MediaStatus>(client_->mediaFlags()); | 215 | return static_cast<OxideQQuickWebView::MediaStatus>(client_->mediaFlags()); |
167 | 215 | } | 216 | } |
168 | 216 | 217 | ||
169 | 218 | void ContextMenuContext::copyImage() const { | ||
170 | 219 | OxideQQuickWebView::MediaType media_type = mediaType(); | ||
171 | 220 | if (media_type != OxideQQuickWebView::MediaTypeImage && | ||
172 | 221 | media_type != OxideQQuickWebView::MediaTypeCanvas) { | ||
173 | 222 | qWarning() << "ContextMenuContext::copyImage(): not an image"; | ||
174 | 223 | return; | ||
175 | 224 | } | ||
176 | 225 | |||
177 | 226 | if (!hasImageContents()) { | ||
178 | 227 | qWarning() << "ContextMenuContext::copyImage(): image has no contents"; | ||
179 | 228 | return; | ||
180 | 229 | } | ||
181 | 230 | |||
182 | 231 | client_->copyImage(); | ||
183 | 232 | } | ||
184 | 233 | |||
185 | 217 | void ContextMenuContext::saveLink() const { | 234 | void ContextMenuContext::saveLink() const { |
186 | 218 | if (linkUrl().isValid()) { | 235 | if (linkUrl().isValid()) { |
187 | 219 | client_->saveLink(); | 236 | client_->saveLink(); |
188 | diff --git a/qt/tests/qmltests/api/tst_WebView_contextMenu.qml b/qt/tests/qmltests/api/tst_WebView_contextMenu.qml | |||
189 | index 6017a1b..f8954b2 100644 | |||
190 | --- a/qt/tests/qmltests/api/tst_WebView_contextMenu.qml | |||
191 | +++ b/qt/tests/qmltests/api/tst_WebView_contextMenu.qml | |||
192 | @@ -96,6 +96,14 @@ TestWebView { | |||
193 | 96 | compare(model.isEditable, data.isEditable); | 96 | compare(model.isEditable, data.isEditable); |
194 | 97 | } | 97 | } |
195 | 98 | 98 | ||
196 | 99 | function test_WebView_contextMenu_copyImage() { | ||
197 | 100 | ClipboardTestUtils.clearClipboard(); | ||
198 | 101 | verify(!ClipboardTestUtils.hasImage()); | ||
199 | 102 | invokeContextMenu("image"); | ||
200 | 103 | webView.currentContextMenu.contextModel.copyImage(); | ||
201 | 104 | verify(TestUtils.waitFor(ClipboardTestUtils.hasImage)); | ||
202 | 105 | } | ||
203 | 106 | |||
204 | 99 | function test_WebView_contextMenu_saveLink() { | 107 | function test_WebView_contextMenu_saveLink() { |
205 | 100 | invokeContextMenu("hyperlink"); | 108 | invokeContextMenu("hyperlink"); |
206 | 101 | var model = webView.currentContextMenu.contextModel; | 109 | var model = webView.currentContextMenu.contextModel; |
207 | diff --git a/qt/tests/qmltests/qml_test_support.cc b/qt/tests/qmltests/qml_test_support.cc | |||
208 | index 4c464c0..1de24a5 100644 | |||
209 | --- a/qt/tests/qmltests/qml_test_support.cc | |||
210 | +++ b/qt/tests/qmltests/qml_test_support.cc | |||
211 | @@ -1,5 +1,5 @@ | |||
212 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
214 | 2 | // Copyright (C) 2013-2015 Canonical Ltd. | 2 | // Copyright (C) 2013-2016 Canonical Ltd. |
215 | 3 | 3 | ||
216 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
217 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
218 | @@ -68,6 +68,10 @@ void ExternalProtocolHandler::setScheme(const QString& scheme) { | |||
219 | 68 | 68 | ||
220 | 69 | ClipboardTestUtils::ClipboardTestUtils() {} | 69 | ClipboardTestUtils::ClipboardTestUtils() {} |
221 | 70 | 70 | ||
222 | 71 | bool ClipboardTestUtils::hasImage() const { | ||
223 | 72 | return QGuiApplication::clipboard()->mimeData()->hasImage(); | ||
224 | 73 | } | ||
225 | 74 | |||
226 | 71 | void ClipboardTestUtils::copyToClipboard(const QString& mimeType, | 75 | void ClipboardTestUtils::copyToClipboard(const QString& mimeType, |
227 | 72 | const QString& data) { | 76 | const QString& data) { |
228 | 73 | QMimeData * mime_data = new QMimeData(); | 77 | QMimeData * mime_data = new QMimeData(); |
229 | diff --git a/qt/tests/qmltests/qml_test_support.h b/qt/tests/qmltests/qml_test_support.h | |||
230 | index 8d400bd..ac0f904 100644 | |||
231 | --- a/qt/tests/qmltests/qml_test_support.h | |||
232 | +++ b/qt/tests/qmltests/qml_test_support.h | |||
233 | @@ -58,6 +58,8 @@ class ClipboardTestUtils : public QObject { | |||
234 | 58 | public: | 58 | public: |
235 | 59 | ClipboardTestUtils(); | 59 | ClipboardTestUtils(); |
236 | 60 | 60 | ||
237 | 61 | Q_INVOKABLE bool hasImage() const; | ||
238 | 62 | |||
239 | 61 | Q_INVOKABLE void copyToClipboard(const QString& mimeType, | 63 | Q_INVOKABLE void copyToClipboard(const QString& mimeType, |
240 | 62 | const QString& data); | 64 | const QString& data); |
241 | 63 | 65 | ||
242 | diff --git a/shared/browser/oxide_web_context_menu.cc b/shared/browser/oxide_web_context_menu.cc | |||
243 | index 718b7f9..6efa9f2 100644 | |||
244 | --- a/shared/browser/oxide_web_context_menu.cc | |||
245 | +++ b/shared/browser/oxide_web_context_menu.cc | |||
246 | @@ -1,5 +1,5 @@ | |||
247 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
249 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
250 | 3 | 3 | ||
251 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
252 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
253 | @@ -79,6 +79,13 @@ void WebContextMenu::Close() { | |||
254 | 79 | content::BrowserThread::UI, FROM_HERE, this); | 79 | content::BrowserThread::UI, FROM_HERE, this); |
255 | 80 | } | 80 | } |
256 | 81 | 81 | ||
257 | 82 | void WebContextMenu::CopyImage() const { | ||
258 | 83 | if ((params_.media_type == blink::WebContextMenuData::MediaTypeCanvas) || | ||
259 | 84 | (params_.media_type == blink::WebContextMenuData::MediaTypeImage)) { | ||
260 | 85 | render_frame_host_->GetRenderViewHost()->CopyImageAt(params_.x, params_.y); | ||
261 | 86 | } | ||
262 | 87 | } | ||
263 | 88 | |||
264 | 82 | void WebContextMenu::SaveLink() const { | 89 | void WebContextMenu::SaveLink() const { |
265 | 83 | content::BrowserContext* context = web_contents()->GetBrowserContext(); | 90 | content::BrowserContext* context = web_contents()->GetBrowserContext(); |
266 | 84 | content::DownloadManager* dlm = | 91 | content::DownloadManager* dlm = |
267 | diff --git a/shared/browser/oxide_web_context_menu.h b/shared/browser/oxide_web_context_menu.h | |||
268 | index 24f9277..8ca6d35 100644 | |||
269 | --- a/shared/browser/oxide_web_context_menu.h | |||
270 | +++ b/shared/browser/oxide_web_context_menu.h | |||
271 | @@ -1,5 +1,5 @@ | |||
272 | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: | 1 | // vim:expandtab:shiftwidth=2:tabstop=2: |
274 | 2 | // Copyright (C) 2015 Canonical Ltd. | 2 | // Copyright (C) 2015-2016 Canonical Ltd. |
275 | 3 | 3 | ||
276 | 4 | // This library is free software; you can redistribute it and/or | 4 | // This library is free software; you can redistribute it and/or |
277 | 5 | // modify it under the terms of the GNU Lesser General Public | 5 | // modify it under the terms of the GNU Lesser General Public |
278 | @@ -56,6 +56,7 @@ class OXIDE_SHARED_EXPORT WebContextMenu : public content::WebContentsObserver { | |||
279 | 56 | 56 | ||
280 | 57 | content::ContextMenuParams params_; | 57 | content::ContextMenuParams params_; |
281 | 58 | 58 | ||
282 | 59 | void CopyImage() const; | ||
283 | 59 | void SaveLink() const; | 60 | void SaveLink() const; |
284 | 60 | void SaveMedia() const; | 61 | void SaveMedia() const; |
285 | 61 | 62 |
Thanks, I've left a few small comments inline