mirror of https://github.com/procxx/kepka.git
				
				
				
			
		
			
				
	
	
		
			241 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
| This file is part of Telegram Desktop,
 | |
| the official desktop version of Telegram messaging app, see https://telegram.org
 | |
| 
 | |
| Telegram Desktop is free software: you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation, either version 3 of the License, or
 | |
| (at your option) any later version.
 | |
| 
 | |
| It is distributed in the hope that it will be useful,
 | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | |
| GNU General Public License for more details.
 | |
| 
 | |
| In addition, as a special exception, the copyright holders give permission
 | |
| to link the code of portions of this program with the OpenSSL library.
 | |
| 
 | |
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | |
| Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | |
| */
 | |
| #include "media/player/media_player_list.h"
 | |
| 
 | |
| #include "media/player/media_player_instance.h"
 | |
| #include "overview/overview_layout.h"
 | |
| #include "styles/style_media_player.h"
 | |
| #include "history/history_media.h"
 | |
| 
 | |
| namespace Media {
 | |
| namespace Player {
 | |
| 
 | |
| ListWidget::ListWidget(QWidget *parent) : TWidget(parent) {
 | |
| 	setMouseTracking(true);
 | |
| 	playlistUpdated();
 | |
| 	subscribe(instance()->playlistChangedNotifier(), [this](AudioMsgId::Type type) { playlistUpdated(); });
 | |
| 	subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
 | |
| 		itemRemoved(item);
 | |
| 	});
 | |
| }
 | |
| 
 | |
| ListWidget::~ListWidget() {
 | |
| 	auto layouts = base::take(_layouts);
 | |
| 	for_const (auto layout, layouts) {
 | |
| 		delete layout;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ListWidget::paintEvent(QPaintEvent *e) {
 | |
| 	Painter p(this);
 | |
| 
 | |
| 	auto clip = e->rect();
 | |
| 	Overview::Layout::PaintContext context(getms(), false);
 | |
| 	int y = marginTop();
 | |
| 	for_const (auto layout, _list) {
 | |
| 		auto layoutHeight = layout->height();
 | |
| 		if (y + layoutHeight > clip.y()) {
 | |
| 			if (y >= clip.y() + clip.height()) break;
 | |
| 
 | |
| 			p.translate(0, y);
 | |
| 			layout->paint(p, clip.translated(0, -y), TextSelection(), &context);
 | |
| 			p.translate(0, -y);
 | |
| 		}
 | |
| 		y += layoutHeight;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ListWidget::mousePressEvent(QMouseEvent *e) {
 | |
| 	if (e->button() != Qt::LeftButton) return;
 | |
| 
 | |
| 	ClickHandler::pressed();
 | |
| }
 | |
| 
 | |
| void ListWidget::mouseReleaseEvent(QMouseEvent *e) {
 | |
| 	ClickHandlerPtr activated = ClickHandler::unpressed();
 | |
| 	if (!ClickHandler::getActive() && _cursor != style::cur_default) {
 | |
| 		_cursor = style::cur_default;
 | |
| 		setCursor(_cursor);
 | |
| 	}
 | |
| 	if (activated) {
 | |
| 		App::activateClickHandler(activated, e->button());
 | |
| 		return;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ListWidget::mouseMoveEvent(QMouseEvent *e) {
 | |
| 	auto m = e->pos();
 | |
| 
 | |
| 	ClickHandlerPtr lnk;
 | |
| 	ClickHandlerHost *lnkhost = nullptr;
 | |
| 	HistoryItem *item = nullptr;
 | |
| 	HistoryCursorState cursorState = HistoryDefaultCursorState;
 | |
| 
 | |
| 	int y = marginTop();
 | |
| 	for_const (auto layout, _list) {
 | |
| 		auto layoutHeight = layout->height();
 | |
| 		if (y + layoutHeight > m.y()) {
 | |
| 			if (y <= m.y()) {
 | |
| 				if (auto media = layout->toMediaItem()) {
 | |
| 					item = media->getItem();
 | |
| 					media->getState(lnk, cursorState, m - QPoint(0, y));
 | |
| 					lnkhost = media;
 | |
| 				}
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 		y += layoutHeight;
 | |
| 	}
 | |
| 
 | |
| 	auto cur = lnk ? style::cur_pointer : style::cur_default;
 | |
| 	if (cur != _cursor) {
 | |
| 		setCursor(_cursor = cur);
 | |
| 	}
 | |
| 
 | |
| 	auto lnkChanged = ClickHandler::setActive(lnk, lnkhost);
 | |
| 	if (item != App::mousedItem()) {
 | |
| 		repaintItem(App::mousedItem());
 | |
| 		App::mousedItem(item);
 | |
| 		repaintItem(App::mousedItem());
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ListWidget::ui_repaintHistoryItem(not_null<const HistoryItem*> item) {
 | |
| 	repaintItem(item);
 | |
| }
 | |
| 
 | |
| void ListWidget::repaintItem(const HistoryItem *item) {
 | |
| 	if (!item) return;
 | |
| 
 | |
| 	auto layoutIt = _layouts.constFind(item->fullId());
 | |
| 	if (layoutIt != _layouts.cend()) {
 | |
| 		int y = 0;
 | |
| 		for_const (auto layout, _list) {
 | |
| 			auto layoutHeight = layout->height();
 | |
| 			if (layout->getItem() == item) {
 | |
| 				update(0, y, width(), layoutHeight);
 | |
| 				break;
 | |
| 			}
 | |
| 			y += layoutHeight;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void ListWidget::itemRemoved(HistoryItem *item) {
 | |
| 	auto layoutIt = _layouts.find(item->fullId());
 | |
| 	if (layoutIt != _layouts.cend()) {
 | |
| 		auto layout = layoutIt.value();
 | |
| 		_layouts.erase(layoutIt);
 | |
| 
 | |
| 		for (int i = 0, count = _list.size(); i != count; ++i) {
 | |
| 			if (_list[i] == layout) {
 | |
| 				_list.removeAt(i);
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 		delete layout;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| QRect ListWidget::getCurrentTrackGeometry() const {
 | |
| 	auto top = marginTop();
 | |
| 	auto current = instance()->current(AudioMsgId::Type::Song);
 | |
| 	auto fullMsgId = current.contextId();
 | |
| 	for_const (auto layout, _list) {
 | |
| 		auto layoutHeight = layout->height();
 | |
| 		if (layout->getItem()->fullId() == fullMsgId) {
 | |
| 			return QRect(0, top, width(), layoutHeight);
 | |
| 		}
 | |
| 		top += layoutHeight;
 | |
| 	}
 | |
| 	return QRect(0, height(), width(), 0);
 | |
| }
 | |
| 
 | |
| int ListWidget::resizeGetHeight(int newWidth) {
 | |
| 	auto result = 0;
 | |
| 	for_const (auto layout, _list) {
 | |
| 		result += layout->resizeGetHeight(newWidth);
 | |
| 	}
 | |
| 	return (result > 0) ? (marginTop() + result) : 0;
 | |
| }
 | |
| 
 | |
| int ListWidget::marginTop() const {
 | |
| 	return st::mediaPlayerListMarginTop;
 | |
| }
 | |
| 
 | |
| void ListWidget::playlistUpdated() {
 | |
| 	auto newHeight = 0;
 | |
| 
 | |
| 	auto playlist = instance()->playlist(AudioMsgId::Type::Song);
 | |
| 	auto playlistSize = playlist.size();
 | |
| 	auto existingSize = _list.size();
 | |
| 	if (playlistSize > existingSize) {
 | |
| 		_list.reserve(playlistSize);
 | |
| 	}
 | |
| 
 | |
| 	int existingIndex = 0;
 | |
| 	for (int i = 0; i != playlistSize; ++i) {
 | |
| 		auto &msgId = playlist[i];
 | |
| 		if (existingIndex < existingSize && _list[existingIndex]->getItem()->fullId() == msgId) {
 | |
| 			newHeight += _list[existingIndex]->height();
 | |
| 			++existingIndex;
 | |
| 			continue;
 | |
| 		}
 | |
| 		auto layoutIt = _layouts.constFind(msgId);
 | |
| 		if (layoutIt == _layouts.cend()) {
 | |
| 			if (auto item = App::histItemById(msgId)) {
 | |
| 				if (auto media = item->getMedia()) {
 | |
| 					if (media->type() == MediaTypeMusicFile) {
 | |
| 						layoutIt = _layouts.insert(msgId, new Overview::Layout::Document(media->getDocument(), item, st::mediaPlayerFileLayout));
 | |
| 						layoutIt.value()->initDimensions();
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if (layoutIt != _layouts.cend()) {
 | |
| 			auto layout = layoutIt.value();
 | |
| 			if (existingIndex < existingSize) {
 | |
| 				_list[existingIndex] = layout;
 | |
| 			} else {
 | |
| 				_list.push_back(layout);
 | |
| 				++existingSize;
 | |
| 			}
 | |
| 			++existingIndex;
 | |
| 			newHeight += layout->resizeGetHeight(width());
 | |
| 		}
 | |
| 	}
 | |
| 	while (existingIndex < existingSize) {
 | |
| 		_list.pop_back();
 | |
| 		--existingSize;
 | |
| 	}
 | |
| 
 | |
| 	if (newHeight > 0) {
 | |
| 		newHeight += marginTop();
 | |
| 	}
 | |
| 	if (newHeight != height()) {
 | |
| 		resize(width(), newHeight);
 | |
| 		emit heightUpdated();
 | |
| 	}
 | |
| }
 | |
| 
 | |
| } // namespace Player
 | |
| } // namespace Media
 |