/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "data/data_file_click_handler.h" #include "core/click_handler_types.h" #include "core/file_utilities.h" #include "core/application.h" #include "data/data_document.h" #include "data/data_session.h" #include "data/data_download_manager.h" #include "data/data_photo.h" #include "main/main_session.h" FileClickHandler::FileClickHandler(FullMsgId context) : _context(context) { } void FileClickHandler::setMessageId(FullMsgId context) { _context = context; } FullMsgId FileClickHandler::context() const { return _context; } not_null DocumentClickHandler::document() const { return _document; } DocumentWrappedClickHandler::DocumentWrappedClickHandler( ClickHandlerPtr wrapped, not_null document, FullMsgId context) : DocumentClickHandler(document, context) , _wrapped(wrapped) { } void DocumentWrappedClickHandler::onClickImpl() const { _wrapped->onClick({ Qt::LeftButton }); } DocumentClickHandler::DocumentClickHandler( not_null document, FullMsgId context) : FileClickHandler(context) , _document(document) { setProperty( kDocumentLinkMediaProperty, reinterpret_cast(_document.get())); } QString DocumentClickHandler::tooltip() const { return property(kDocumentFilenameTooltipProperty).value(); } DocumentOpenClickHandler::DocumentOpenClickHandler( not_null document, Fn &&callback, FullMsgId context) : DocumentClickHandler(document, context) , _handler(std::move(callback)) { Expects(_handler != nullptr); } void DocumentOpenClickHandler::onClickImpl() const { _handler(context()); } void DocumentSaveClickHandler::Save( Data::FileOrigin origin, not_null data, Mode mode, Fn started) { if (data->isNull()) { return; } auto savename = QString(); if (mode == Mode::ToCacheOrFile && data->saveToCache()) { data->save(origin, savename); return; } InvokeQueued(qApp, crl::guard(&data->session(), [=] { // If we call file dialog synchronously, it will stop // background thread timers from working which would // stop audio playback in voice chats / live streams. if (mode != Mode::ToNewFile && data->saveFromData()) { if (started) { started(); } return; } const auto filepath = data->filepath(true); const auto fileinfo = QFileInfo( ); const auto filedir = filepath.isEmpty() ? QDir() : fileinfo.dir(); const auto filename = filepath.isEmpty() ? QString() : fileinfo.fileName(); const auto savename = DocumentFileNameForSave( data, (mode == Mode::ToNewFile), filename, filedir); if (!savename.isEmpty()) { data->save(origin, savename); if (started) { started(); } } })); } void DocumentSaveClickHandler::SaveAndTrack( FullMsgId itemId, not_null document, Mode mode, Fn started) { Save(itemId ? itemId : Data::FileOrigin(), document, mode, [=] { if (document->loading() && !document->loadingFilePath().isEmpty()) { if (const auto item = document->owner().message(itemId)) { Core::App().downloadManager().addLoading({ .item = item, .document = document, }); } } if (started) { started(); } }); } void DocumentSaveClickHandler::onClickImpl() const { SaveAndTrack(context(), document()); } DocumentCancelClickHandler::DocumentCancelClickHandler( not_null document, Fn &&callback, FullMsgId context) : DocumentClickHandler(document, context) , _handler(std::move(callback)) { } void DocumentCancelClickHandler::onClickImpl() const { const auto data = document(); if (data->isNull()) { return; } else if (data->uploading() && _handler) { _handler(context()); } else { data->cancel(); } } void DocumentOpenWithClickHandler::Open( Data::FileOrigin origin, not_null data) { if (data->isNull()) { return; } data->saveFromDataSilent(); const auto path = data->filepath(true); if (!path.isEmpty()) { File::OpenWith(path); } else { DocumentSaveClickHandler::Save( origin, data, DocumentSaveClickHandler::Mode::ToFile); } } void DocumentOpenWithClickHandler::onClickImpl() const { Open(context(), document()); } PhotoClickHandler::PhotoClickHandler( not_null photo, FullMsgId context, PeerData *peer) : FileClickHandler(context) , _photo(photo) , _peer(peer) { setProperty( kPhotoLinkMediaProperty, reinterpret_cast(_photo.get())); } not_null PhotoClickHandler::photo() const { return _photo; } PeerData *PhotoClickHandler::peer() const { return _peer; } PhotoOpenClickHandler::PhotoOpenClickHandler( not_null photo, Fn &&callback, FullMsgId context) : PhotoClickHandler(photo, context) , _handler(std::move(callback)) { Expects(_handler != nullptr); } void PhotoOpenClickHandler::onClickImpl() const { _handler(context()); } void PhotoSaveClickHandler::onClickImpl() const { const auto data = photo(); if (data->isNull()) { return; } else { data->clearFailed(Data::PhotoSize::Large); data->load(context()); } } PhotoCancelClickHandler::PhotoCancelClickHandler( not_null photo, Fn &&callback, FullMsgId context) : PhotoClickHandler(photo, context) , _handler(std::move(callback)) { } void PhotoCancelClickHandler::onClickImpl() const { const auto data = photo(); if (data->isNull()) { return; } else if (data->uploading() && _handler) { _handler(context()); } else { data->cancel(); } }