data_file_click_handler.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "data/data_file_click_handler.h"
  8. #include "core/click_handler_types.h"
  9. #include "core/file_utilities.h"
  10. #include "core/application.h"
  11. #include "data/data_document.h"
  12. #include "data/data_session.h"
  13. #include "data/data_download_manager.h"
  14. #include "data/data_photo.h"
  15. #include "main/main_session.h"
  16. FileClickHandler::FileClickHandler(FullMsgId context)
  17. : _context(context) {
  18. }
  19. void FileClickHandler::setMessageId(FullMsgId context) {
  20. _context = context;
  21. }
  22. FullMsgId FileClickHandler::context() const {
  23. return _context;
  24. }
  25. not_null<DocumentData*> DocumentClickHandler::document() const {
  26. return _document;
  27. }
  28. DocumentWrappedClickHandler::DocumentWrappedClickHandler(
  29. ClickHandlerPtr wrapped,
  30. not_null<DocumentData*> document,
  31. FullMsgId context)
  32. : DocumentClickHandler(document, context)
  33. , _wrapped(wrapped) {
  34. }
  35. void DocumentWrappedClickHandler::onClickImpl() const {
  36. _wrapped->onClick({ Qt::LeftButton });
  37. }
  38. DocumentClickHandler::DocumentClickHandler(
  39. not_null<DocumentData*> document,
  40. FullMsgId context)
  41. : FileClickHandler(context)
  42. , _document(document) {
  43. setProperty(
  44. kDocumentLinkMediaProperty,
  45. reinterpret_cast<qulonglong>(_document.get()));
  46. }
  47. QString DocumentClickHandler::tooltip() const {
  48. return property(kDocumentFilenameTooltipProperty).value<QString>();
  49. }
  50. DocumentOpenClickHandler::DocumentOpenClickHandler(
  51. not_null<DocumentData*> document,
  52. Fn<void(FullMsgId)> &&callback,
  53. FullMsgId context)
  54. : DocumentClickHandler(document, context)
  55. , _handler(std::move(callback)) {
  56. Expects(_handler != nullptr);
  57. }
  58. void DocumentOpenClickHandler::onClickImpl() const {
  59. _handler(context());
  60. }
  61. void DocumentSaveClickHandler::Save(
  62. Data::FileOrigin origin,
  63. not_null<DocumentData*> data,
  64. Mode mode,
  65. Fn<void()> started) {
  66. if (data->isNull()) {
  67. return;
  68. }
  69. auto savename = QString();
  70. if (mode == Mode::ToCacheOrFile && data->saveToCache()) {
  71. data->save(origin, savename);
  72. return;
  73. }
  74. InvokeQueued(qApp, crl::guard(&data->session(), [=] {
  75. // If we call file dialog synchronously, it will stop
  76. // background thread timers from working which would
  77. // stop audio playback in voice chats / live streams.
  78. if (mode != Mode::ToNewFile && data->saveFromData()) {
  79. if (started) {
  80. started();
  81. }
  82. return;
  83. }
  84. const auto filepath = data->filepath(true);
  85. const auto fileinfo = QFileInfo(
  86. );
  87. const auto filedir = filepath.isEmpty()
  88. ? QDir()
  89. : fileinfo.dir();
  90. const auto filename = filepath.isEmpty()
  91. ? QString()
  92. : fileinfo.fileName();
  93. const auto savename = DocumentFileNameForSave(
  94. data,
  95. (mode == Mode::ToNewFile),
  96. filename,
  97. filedir);
  98. if (!savename.isEmpty()) {
  99. data->save(origin, savename);
  100. if (started) {
  101. started();
  102. }
  103. }
  104. }));
  105. }
  106. void DocumentSaveClickHandler::SaveAndTrack(
  107. FullMsgId itemId,
  108. not_null<DocumentData*> document,
  109. Mode mode,
  110. Fn<void()> started) {
  111. Save(itemId ? itemId : Data::FileOrigin(), document, mode, [=] {
  112. if (document->loading() && !document->loadingFilePath().isEmpty()) {
  113. if (const auto item = document->owner().message(itemId)) {
  114. Core::App().downloadManager().addLoading({
  115. .item = item,
  116. .document = document,
  117. });
  118. }
  119. }
  120. if (started) {
  121. started();
  122. }
  123. });
  124. }
  125. void DocumentSaveClickHandler::onClickImpl() const {
  126. SaveAndTrack(context(), document());
  127. }
  128. DocumentCancelClickHandler::DocumentCancelClickHandler(
  129. not_null<DocumentData*> document,
  130. Fn<void(FullMsgId)> &&callback,
  131. FullMsgId context)
  132. : DocumentClickHandler(document, context)
  133. , _handler(std::move(callback)) {
  134. }
  135. void DocumentCancelClickHandler::onClickImpl() const {
  136. const auto data = document();
  137. if (data->isNull()) {
  138. return;
  139. } else if (data->uploading() && _handler) {
  140. _handler(context());
  141. } else {
  142. data->cancel();
  143. }
  144. }
  145. void DocumentOpenWithClickHandler::Open(
  146. Data::FileOrigin origin,
  147. not_null<DocumentData*> data) {
  148. if (data->isNull()) {
  149. return;
  150. }
  151. data->saveFromDataSilent();
  152. const auto path = data->filepath(true);
  153. if (!path.isEmpty()) {
  154. File::OpenWith(path);
  155. } else {
  156. DocumentSaveClickHandler::Save(
  157. origin,
  158. data,
  159. DocumentSaveClickHandler::Mode::ToFile);
  160. }
  161. }
  162. void DocumentOpenWithClickHandler::onClickImpl() const {
  163. Open(context(), document());
  164. }
  165. PhotoClickHandler::PhotoClickHandler(
  166. not_null<PhotoData*> photo,
  167. FullMsgId context,
  168. PeerData *peer)
  169. : FileClickHandler(context)
  170. , _photo(photo)
  171. , _peer(peer) {
  172. setProperty(
  173. kPhotoLinkMediaProperty,
  174. reinterpret_cast<qulonglong>(_photo.get()));
  175. }
  176. not_null<PhotoData*> PhotoClickHandler::photo() const {
  177. return _photo;
  178. }
  179. PeerData *PhotoClickHandler::peer() const {
  180. return _peer;
  181. }
  182. PhotoOpenClickHandler::PhotoOpenClickHandler(
  183. not_null<PhotoData*> photo,
  184. Fn<void(FullMsgId)> &&callback,
  185. FullMsgId context)
  186. : PhotoClickHandler(photo, context)
  187. , _handler(std::move(callback)) {
  188. Expects(_handler != nullptr);
  189. }
  190. void PhotoOpenClickHandler::onClickImpl() const {
  191. _handler(context());
  192. }
  193. void PhotoSaveClickHandler::onClickImpl() const {
  194. const auto data = photo();
  195. if (data->isNull()) {
  196. return;
  197. } else {
  198. data->clearFailed(Data::PhotoSize::Large);
  199. data->load(context());
  200. }
  201. }
  202. PhotoCancelClickHandler::PhotoCancelClickHandler(
  203. not_null<PhotoData*> photo,
  204. Fn<void(FullMsgId)> &&callback,
  205. FullMsgId context)
  206. : PhotoClickHandler(photo, context)
  207. , _handler(std::move(callback)) {
  208. }
  209. void PhotoCancelClickHandler::onClickImpl() const {
  210. const auto data = photo();
  211. if (data->isNull()) {
  212. return;
  213. } else if (data->uploading() && _handler) {
  214. _handler(context());
  215. } else {
  216. data->cancel();
  217. }
  218. }