Fix copy selected items text in old and new lists.

This commit is contained in:
John Preston 2018-01-27 20:26:24 +03:00
parent e5f3bed801
commit 600737c44f
9 changed files with 175 additions and 169 deletions

View File

@ -130,6 +130,8 @@ QString WithCaptionNotificationText(
caption);
}
} // namespace
TextWithEntities WithCaptionClipboardText(
const QString &attachType,
TextWithEntities &&caption) {
@ -143,8 +145,6 @@ TextWithEntities WithCaptionClipboardText(
return result;
}
} // namespace
Media::Media(not_null<HistoryItem*> parent) : _parent(parent) {
}

View File

@ -364,4 +364,8 @@ private:
};
TextWithEntities WithCaptionClipboardText(
const QString &attachType,
TextWithEntities &&caption);
} // namespace Data

View File

@ -1767,56 +1767,46 @@ TextWithEntities HistoryInner::getSelectedText() const {
}
const auto timeFormat = qsl(", [dd.MM.yy hh:mm]\n");
auto groupLeadersAdded = base::flat_set<not_null<Element*>>();
auto groups = base::flat_set<not_null<const Data::Group*>>();
auto fullSize = 0;
auto texts = base::flat_map<std::pair<int, MsgId>, TextWithEntities>();
auto texts = base::flat_map<Data::MessagePosition, TextWithEntities>();
const auto addItem = [&](not_null<HistoryView::Element*> view) {
const auto item = view->data();
const auto wrapItem = [&](
not_null<HistoryItem*> item,
TextWithEntities &&unwrapped) {
auto time = item->date.toString(timeFormat);
auto part = TextWithEntities();
auto unwrapped = HistoryItemText(item);
auto size = item->author()->name.size()
+ time.size()
+ unwrapped.text.size();
part.text.reserve(size);
part.text.append(item->author()->name).append(time);
TextUtilities::Append(part, std::move(unwrapped));
texts.emplace(item->position(), part);
fullSize += size;
};
const auto addItem = [&](not_null<HistoryItem*> item) {
wrapItem(item, HistoryItemText(item));
};
const auto addGroup = [&](not_null<const Data::Group*> group) {
Expects(!group->items.empty());
auto y = itemTop(view);
if (y >= 0) {
part.text.append(item->author()->name).append(time);
TextUtilities::Append(part, std::move(unwrapped));
texts.emplace(std::make_pair(y, item->id), part);
fullSize += size;
}
wrapItem(group->items.back(), HistoryGroupText(group));
};
for (const auto [item, selection] : selected) {
const auto view = item->mainView();
if (!view) {
continue;
}
if (const auto group = Auth().data().groups().find(item)) {
// #TODO group copy
//if (groupLeadersAdded.contains(group->leader)) {
// continue;
//}
//const auto leaderSelection = computeRenderSelection(
// &selected,
// group->leader);
//if (leaderSelection == FullSelection) {
// groupLeadersAdded.emplace(group->leader);
// addItem(group->leader);
//} else if (view == group->leader) {
// const auto leaderFullSelection = AddGroupItemSelection(
// TextSelection(),
// int(group->others.size()));
// addItem(view, leaderFullSelection);
//} else {
// addItem(view);
//}
if (groups.contains(group)) {
continue;
}
if (isSelectedGroup(&selected, group)) {
groups.emplace(group);
addGroup(group);
} else {
addItem(item);
}
} else {
addItem(view);
addItem(item);
}
}
@ -2686,16 +2676,22 @@ bool HistoryInner::isSelected(
return (i != toItems->cend()) && (i->second == FullSelection);
}
bool HistoryInner::isSelectedGroup(
not_null<SelectedItems*> toItems,
not_null<const Data::Group*> group) const {
for (const auto other : group->items) {
if (!isSelected(toItems, other)) {
return false;
}
}
return true;
}
bool HistoryInner::isSelectedAsGroup(
not_null<SelectedItems*> toItems,
not_null<HistoryItem*> item) const {
if (const auto group = Auth().data().groups().find(item)) {
for (const auto other : group->items) {
if (!isSelected(toItems, other)) {
return false;
}
}
return true;
return isSelectedGroup(toItems, group);
}
return isSelected(toItems, item);
}

View File

@ -13,6 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/scroll_area.h"
#include "history/view/history_view_top_bar_widget.h"
namespace Data {
class Group;
} // namespace Data
namespace HistoryView {
class ElementDelegate;
struct TextState;
@ -244,6 +248,9 @@ private:
bool isSelected(
not_null<SelectedItems*> toItems,
not_null<HistoryItem*> item) const;
bool isSelectedGroup(
not_null<SelectedItems*> toItems,
not_null<const Data::Group*> group) const;
bool isSelectedAsGroup(
not_null<SelectedItems*> toItems,
not_null<HistoryItem*> item) const;

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_components.h"
#include "data/data_media_types.h"
#include "data/data_web_page.h"
#include "data/data_groups.h"
#include "lang/lang_keys.h"
#include "ui/text_options.h"
@ -55,11 +56,27 @@ TextWithEntities WrapAsForwarded(
return result;
}
TextWithEntities WrapAsItem(
not_null<HistoryItem*> item,
TextWithEntities &&result) {
if (const auto reply = item->Get<HistoryMessageReply>()) {
if (const auto message = reply->replyToMsg) {
result = WrapAsReply(std::move(result), message);
}
}
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
result = WrapAsForwarded(std::move(result), forwarded);
}
return result;
}
TextWithEntities HistoryItemText(not_null<HistoryItem*> item) {
const auto media = item->media();
auto textResult = item->clipboardText();
auto mediaResult = media ? media->clipboardText() : TextWithEntities();
auto textResult = mediaResult.text.isEmpty()
? item->clipboardText()
: TextWithEntities();
auto logEntryOriginalResult = [&] {
const auto entry = item->Get<HistoryMessageLogEntryOriginal>();
if (!entry) {
@ -94,13 +111,26 @@ TextWithEntities HistoryItemText(not_null<HistoryItem*> item) {
result.text += qstr("\n\n");
TextUtilities::Append(result, std::move(logEntryOriginalResult));
}
if (const auto reply = item->Get<HistoryMessageReply>()) {
if (const auto message = reply->replyToMsg) {
result = WrapAsReply(std::move(result), message);
}
}
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
result = WrapAsForwarded(std::move(result), forwarded);
}
return result;
return WrapAsItem(item, std::move(result));
}
TextWithEntities HistoryGroupText(not_null<const Data::Group*> group) {
Expects(!group->items.empty());
auto caption = [&] {
const auto first = begin(group->items);
const auto result = (*first)->clipboardText();
if (result.text.isEmpty()) {
return result;
}
for (auto i = first + 1; i != end(group->items); ++i) {
if (!(*i)->clipboardText().text.isEmpty()) {
return TextWithEntities();
}
}
return result;
}();
return WrapAsItem(group->items.back(), Data::WithCaptionClipboardText(
lang(lng_in_dlg_album),
std::move(caption)));
}

View File

@ -7,4 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
class HistoryItem;
namespace Data {
class Group;
} // namespace Data
TextWithEntities HistoryItemText(not_null<HistoryItem*> item);
TextWithEntities HistoryGroupText(not_null<const Data::Group*> group);

View File

@ -280,16 +280,6 @@ TextSelection HistoryGroupedMedia::adjustSelection(
TextWithEntities HistoryGroupedMedia::selectedText(
TextSelection selection) const {
return _caption.originalTextWithEntities(selection, ExpandLinksAll);
// #TODO group select
//if (!IsSubGroupSelection(selection)) {
// return WithCaptionSelectedText(
// lang(lng_in_dlg_album),
// _caption,
// selection);
//} else if (IsGroupItemSelection(selection, int(_parts.size()) - 1)) {
// return main()->selectedText(FullSelection);
//}
//return TextWithEntities();
}
void HistoryGroupedMedia::clickHandlerActiveChanged(

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_media_types.h"
#include "history/history_message.h"
#include "history/history_item_components.h"
#include "history/history_item_text.h"
#include "history/view/history_view_context_menu.h"
#include "history/view/history_view_element.h"
#include "history/view/history_view_message.h"
@ -527,53 +528,22 @@ bool ListWidget::overSelectedItems() const {
return false;
}
//bool ListWidget::applyItemSelection(
// SelectedMap &applyTo,
// FullMsgId itemId) const {
// if (applyTo.size() >= MaxSelectedItems) {
// return false;
// }
// auto [iterator, ok] = applyTo.try_emplace(
// itemId,
// SelectionData());
// if (!ok) {
// return false;
// }
// const auto item = App::histItemById(itemId);
// if (!item) {
// applyTo.erase(iterator);
// return false;
// }
// iterator->second.canDelete = item->canDelete();
// iterator->second.canForward = item->allowsForward();
// return true;
//}
//
//void ListWidget::toggleItemSelection(FullMsgId itemId) {
// auto it = _selected.find(itemId);
// if (it == _selected.cend()) {
// if (_selectedTextItem) {
// clearTextSelection();
// }
// if (applyItemSelection(_selected, itemId)) {
// repaintItem(itemId);
// pushSelectedItems();
// }
// } else {
// removeItemSelection(it);
// }
//}
bool ListWidget::isSelectedGroup(
const SelectedMap &applyTo,
not_null<const Data::Group*> group) const {
for (const auto other : group->items) {
if (!applyTo.contains(other->fullId())) {
return false;
}
}
return true;
}
bool ListWidget::isSelectedAsGroup(
const SelectedMap &applyTo,
not_null<HistoryItem*> item) const {
if (const auto group = Auth().data().groups().find(item)) {
for (const auto other : group->items) {
if (!applyTo.contains(other->fullId())) {
return false;
}
}
return true;
return isSelectedGroup(applyTo, group);
}
return applyTo.contains(item->fullId());
}
@ -1135,72 +1105,69 @@ TextWithEntities ListWidget::getSelectedText() const {
return _selectedText;
}
// #TODO selection
//const auto timeFormat = qsl(", [dd.MM.yy hh:mm]\n");
//auto groupLeadersAdded = base::flat_set<not_null<Element*>>();
//auto fullSize = 0;
//auto texts = base::flat_map<std::pair<int, MsgId>, TextWithEntities>();
const auto timeFormat = qsl(", [dd.MM.yy hh:mm]\n");
auto groups = base::flat_set<not_null<const Data::Group*>>();
auto fullSize = 0;
auto texts = std::vector<std::pair<
not_null<HistoryItem*>,
TextWithEntities>>();
texts.reserve(selected.size());
//const auto addItem = [&](
// not_null<HistoryView::Element*> view,
// TextSelection selection) {
// const auto item = view->data();
// auto time = item->date.toString(timeFormat);
// auto part = TextWithEntities();
// auto unwrapped = view->selectedText(selection);
// auto size = item->author()->name.size()
// + time.size()
// + unwrapped.text.size();
// part.text.reserve(size);
const auto wrapItem = [&](
not_null<HistoryItem*> item,
TextWithEntities &&unwrapped) {
auto time = item->date.toString(timeFormat);
auto part = TextWithEntities();
auto size = item->author()->name.size()
+ time.size()
+ unwrapped.text.size();
part.text.reserve(size);
part.text.append(item->author()->name).append(time);
TextUtilities::Append(part, std::move(unwrapped));
texts.push_back(std::make_pair(std::move(item), std::move(part)));
fullSize += size;
};
const auto addItem = [&](not_null<HistoryItem*> item) {
wrapItem(item, HistoryItemText(item));
};
const auto addGroup = [&](not_null<const Data::Group*> group) {
Expects(!group->items.empty());
// auto y = itemTop(view);
// if (y >= 0) {
// part.text.append(item->author()->name).append(time);
// TextUtilities::Append(part, std::move(unwrapped));
// texts.emplace(std::make_pair(y, item->id), part);
// fullSize += size;
// }
//};
wrapItem(group->items.back(), HistoryGroupText(group));
};
//for (const auto [item, selection] : selected) {
// const auto view = item->mainView();
// if (!view) {
// continue;
// }
// if (const auto group = Auth().data().groups().find(item)) {
// // #TODO group copy
// //if (groupLeadersAdded.contains(group->leader)) {
// // continue;
// //}
// //const auto leaderSelection = computeRenderSelection(
// // &selected,
// // group->leader);
// //if (leaderSelection == FullSelection) {
// // groupLeadersAdded.emplace(group->leader);
// // addItem(group->leader, FullSelection);
// //} else if (view == group->leader) {
// // const auto leaderFullSelection = AddGroupItemSelection(
// // TextSelection(),
// // int(group->others.size()));
// // addItem(view, leaderFullSelection);
// //} else {
// // addItem(view, FullSelection);
// //}
// } else {
// addItem(view, FullSelection);
// }
//}
for (const auto [itemId, data] : selected) {
if (const auto item = App::histItemById(itemId)) {
if (const auto group = Auth().data().groups().find(item)) {
if (groups.contains(group)) {
continue;
}
if (isSelectedGroup(selected, group)) {
groups.emplace(group);
addGroup(group);
} else {
addItem(item);
}
} else {
addItem(item);
}
}
}
ranges::sort(texts, [&](
const std::pair<not_null<HistoryItem*>, TextWithEntities> &a,
const std::pair<not_null<HistoryItem*>, TextWithEntities> &b) {
return _delegate->listIsLessInOrder(a.first, b.first);
});
auto result = TextWithEntities();
//auto sep = qsl("\n\n");
//result.text.reserve(fullSize + (texts.size() - 1) * sep.size());
//for (auto i = texts.begin(), e = texts.end(); i != e;) {
// TextUtilities::Append(result, std::move(i->second));
// if (++i != e) {
// result.text.append(sep);
// }
//}
auto sep = qsl("\n\n");
result.text.reserve(fullSize + (texts.size() - 1) * sep.size());
for (auto i = begin(texts), e = end(texts); i != e;) {
TextUtilities::Append(result, std::move(i->second));
if (++i != e) {
result.text.append(sep);
}
}
return result;
}

View File

@ -22,6 +22,10 @@ namespace Window {
class Controller;
} // namespace Window
namespace Data {
class Group;
} // namespace Data
namespace HistoryView {
struct TextState;
@ -288,8 +292,6 @@ private:
void setTextSelection(
not_null<Element*> view,
TextSelection selection);
//bool applyItemSelection(SelectedMap &applyTo, FullMsgId itemId) const;
//void toggleItemSelection(FullMsgId itemId);
bool isGoodForSelection(not_null<HistoryItem*> item) const;
bool isGoodForSelection(
@ -306,6 +308,9 @@ private:
SelectedMap &applyTo,
not_null<HistoryItem*> item,
SelectAction action) const;
bool isSelectedGroup(
const SelectedMap &applyTo,
not_null<const Data::Group*> group) const;
bool isSelectedAsGroup(
const SelectedMap &applyTo,
not_null<HistoryItem*> item) const;