mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Shared media multiple items selection.
This commit is contained in:
parent
66146c382d
commit
54cc3e6315
23 changed files with 1117 additions and 579 deletions
|
@ -64,12 +64,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#error Please add support for your architecture in base/build_config.h
|
||||
#endif
|
||||
|
||||
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
|
||||
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#elif defined(_MSC_VER)
|
||||
|
|
|
@ -109,7 +109,18 @@ public:
|
|||
flat_multi_map_iterator_base_impl operator-(difference_type offset) const {
|
||||
return _impl - offset;
|
||||
}
|
||||
difference_type operator-(const flat_multi_map_iterator_base_impl &right) const {
|
||||
template <
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
difference_type operator-(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
return _impl - right._impl;
|
||||
}
|
||||
reference operator[](difference_type offset) {
|
||||
|
@ -119,13 +130,46 @@ public:
|
|||
return _impl[offset];
|
||||
}
|
||||
|
||||
bool operator==(const flat_multi_map_iterator_base_impl &right) const {
|
||||
template <
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
bool operator==(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
return _impl == right._impl;
|
||||
}
|
||||
bool operator!=(const flat_multi_map_iterator_base_impl &right) const {
|
||||
template <
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
bool operator!=(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
return _impl != right._impl;
|
||||
}
|
||||
bool operator<(const flat_multi_map_iterator_base_impl &right) const {
|
||||
template <
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
bool operator<(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
return _impl < right._impl;
|
||||
}
|
||||
|
||||
|
@ -133,6 +177,15 @@ private:
|
|||
iterator_impl _impl;
|
||||
friend class flat_multi_map<Key, Type, Compare>;
|
||||
|
||||
template <
|
||||
typename OtherKey,
|
||||
typename OtherType,
|
||||
typename OtherCompare,
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
friend class flat_multi_map_iterator_base_impl;
|
||||
|
||||
};
|
||||
|
||||
template <typename Key, typename Type, typename Compare>
|
||||
|
@ -418,10 +471,10 @@ public:
|
|||
return (range.second - range.first);
|
||||
}
|
||||
|
||||
iterator erase(iterator where) {
|
||||
iterator erase(const_iterator where) {
|
||||
return _impl.erase(where._impl);
|
||||
}
|
||||
iterator erase(iterator from, iterator till) {
|
||||
iterator erase(const_iterator from, const_iterator till) {
|
||||
return _impl.erase(from._impl, till._impl);
|
||||
}
|
||||
|
||||
|
@ -525,37 +578,69 @@ public:
|
|||
using parent::erase;
|
||||
using parent::contains;
|
||||
|
||||
iterator insert(const value_type &value) {
|
||||
std::pair<iterator, bool> insert(const value_type &value) {
|
||||
if (this->empty() || compare()(value.first, this->front().first)) {
|
||||
this->_impl.push_front(value);
|
||||
return this->begin();
|
||||
return { this->begin(), true };
|
||||
} else if (compare()(this->back().first, value.first)) {
|
||||
this->_impl.push_back(value);
|
||||
return (this->end() - 1);
|
||||
return { this->end() - 1, true };
|
||||
}
|
||||
auto where = this->getLowerBound(value.first);
|
||||
if (compare()(value.first, where->first)) {
|
||||
return this->_impl.insert(where, value);
|
||||
return { this->_impl.insert(where, value), true };
|
||||
}
|
||||
return this->end();
|
||||
return { where, false };
|
||||
}
|
||||
iterator insert(value_type &&value) {
|
||||
std::pair<iterator, bool> insert(value_type &&value) {
|
||||
if (this->empty() || compare()(value.first, this->front().first)) {
|
||||
this->_impl.push_front(std::move(value));
|
||||
return this->begin();
|
||||
return { this->begin(), true };
|
||||
} else if (compare()(this->back().first, value.first)) {
|
||||
this->_impl.push_back(std::move(value));
|
||||
return (this->end() - 1);
|
||||
return { this->end() - 1, true };
|
||||
}
|
||||
auto where = this->getLowerBound(value.first);
|
||||
if (compare()(value.first, where->first)) {
|
||||
return this->_impl.insert(where, std::move(value));
|
||||
return { this->_impl.insert(where, std::move(value)), true };
|
||||
}
|
||||
return this->end();
|
||||
return { where, false };
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
return this->insert(value_type(std::forward<Args>(args)...));
|
||||
std::pair<iterator, bool> emplace(
|
||||
const Key &key,
|
||||
Args&&... args) {
|
||||
return this->insert(value_type(
|
||||
key,
|
||||
Type(std::forward<Args>(args)...)));
|
||||
}
|
||||
template <typename... Args>
|
||||
std::pair<iterator, bool> try_emplace(
|
||||
const Key &key,
|
||||
Args&&... args) {
|
||||
if (this->empty() || compare()(key, this->front().first)) {
|
||||
this->_impl.push_front(value_type(
|
||||
key,
|
||||
Type(std::forward<Args>(args)...)));
|
||||
return { this->begin(), true };
|
||||
} else if (compare()(this->back().first, key)) {
|
||||
this->_impl.push_back(value_type(
|
||||
key,
|
||||
Type(std::forward<Args>(args)...)));
|
||||
return { this->end() - 1, true };
|
||||
}
|
||||
auto where = this->getLowerBound(key);
|
||||
if (compare()(key, where->first)) {
|
||||
return {
|
||||
this->_impl.insert(
|
||||
where,
|
||||
value_type(
|
||||
key,
|
||||
Type(std::forward<Args>(args)...))),
|
||||
true
|
||||
};
|
||||
}
|
||||
return { where, false };
|
||||
}
|
||||
|
||||
bool remove(const Key &key) {
|
||||
|
|
|
@ -47,6 +47,13 @@ public:
|
|||
flat_multi_set_iterator_base_impl(iterator_impl impl = iterator_impl())
|
||||
: _impl(impl) {
|
||||
}
|
||||
template <typename other_iterator_impl>
|
||||
flat_multi_set_iterator_base_impl(
|
||||
const flat_multi_set_iterator_base_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &other) : _impl(other._impl) {
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
return *_impl;
|
||||
|
@ -82,20 +89,40 @@ public:
|
|||
flat_multi_set_iterator_base_impl operator-(difference_type offset) const {
|
||||
return _impl - offset;
|
||||
}
|
||||
difference_type operator-(const flat_multi_set_iterator_base_impl &right) const {
|
||||
template <typename other_iterator_impl>
|
||||
difference_type operator-(
|
||||
const flat_multi_set_iterator_base_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl - right._impl;
|
||||
}
|
||||
reference operator[](difference_type offset) const {
|
||||
return _impl[offset];
|
||||
}
|
||||
|
||||
bool operator==(const flat_multi_set_iterator_base_impl &right) const {
|
||||
template <typename other_iterator_impl>
|
||||
bool operator==(
|
||||
const flat_multi_set_iterator_base_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl == right._impl;
|
||||
}
|
||||
bool operator!=(const flat_multi_set_iterator_base_impl &right) const {
|
||||
template <typename other_iterator_impl>
|
||||
bool operator!=(
|
||||
const flat_multi_set_iterator_base_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl != right._impl;
|
||||
}
|
||||
bool operator<(const flat_multi_set_iterator_base_impl &right) const {
|
||||
template <typename other_iterator_impl>
|
||||
bool operator<(
|
||||
const flat_multi_set_iterator_base_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl < right._impl;
|
||||
}
|
||||
|
||||
|
@ -104,6 +131,12 @@ private:
|
|||
friend class flat_multi_set<Type, Compare>;
|
||||
friend class flat_set<Type, Compare>;
|
||||
|
||||
template <
|
||||
typename OtherType,
|
||||
typename OtherCompare,
|
||||
typename other_iterator_impl>
|
||||
friend class flat_multi_set_iterator_base_impl;
|
||||
|
||||
Type &wrapped() {
|
||||
return _impl->wrapped();
|
||||
}
|
||||
|
@ -205,43 +238,24 @@ public:
|
|||
using pointer = const Type*;
|
||||
using reference = const Type&;
|
||||
|
||||
class const_iterator;
|
||||
class iterator : public iterator_base {
|
||||
public:
|
||||
using iterator_base::iterator_base;
|
||||
iterator(const iterator_base &other) : iterator_base(other) {
|
||||
}
|
||||
friend class const_iterator;
|
||||
|
||||
};
|
||||
class const_iterator : public const_iterator_base {
|
||||
public:
|
||||
using const_iterator_base::const_iterator_base;
|
||||
const_iterator(const_iterator_base other) : const_iterator_base(other) {
|
||||
}
|
||||
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
|
||||
}
|
||||
|
||||
};
|
||||
class const_reverse_iterator;
|
||||
class reverse_iterator : public reverse_iterator_base {
|
||||
public:
|
||||
using reverse_iterator_base::reverse_iterator_base;
|
||||
reverse_iterator(reverse_iterator_base other)
|
||||
: reverse_iterator_base(other) {
|
||||
}
|
||||
friend class const_reverse_iterator;
|
||||
|
||||
};
|
||||
class const_reverse_iterator : public const_reverse_iterator_base {
|
||||
public:
|
||||
using const_reverse_iterator_base::const_reverse_iterator_base;
|
||||
const_reverse_iterator(const_reverse_iterator_base other)
|
||||
: const_reverse_iterator_base(other) {
|
||||
}
|
||||
const_reverse_iterator(const reverse_iterator &other)
|
||||
: const_reverse_iterator_base(other._impl) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -366,10 +380,10 @@ public:
|
|||
return (range.second - range.first);
|
||||
}
|
||||
|
||||
iterator erase(iterator where) {
|
||||
iterator erase(const_iterator where) {
|
||||
return _impl.erase(where._impl);
|
||||
}
|
||||
iterator erase(iterator from, iterator till) {
|
||||
iterator erase(const_iterator from, const_iterator till) {
|
||||
return _impl.erase(from._impl, till._impl);
|
||||
}
|
||||
|
||||
|
|
|
@ -894,7 +894,9 @@ void GifsListWidget::updateSelected() {
|
|||
}
|
||||
if (col < inlineItems.size()) {
|
||||
sel = row * MatrixRowShift + col;
|
||||
inlineItems.at(col)->getState(lnk, cursor, QPoint(sx, sy));
|
||||
auto result = inlineItems[col]->getState(QPoint(sx, sy), HistoryStateRequest());
|
||||
lnk = result.link;
|
||||
cursor = result.cursor;
|
||||
lnkhost = inlineItems.at(col);
|
||||
} else {
|
||||
row = col = -1;
|
||||
|
|
|
@ -1033,10 +1033,11 @@ void HistoryInner::itemRemoved(not_null<const HistoryItem*> item) {
|
|||
void HistoryInner::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton button) {
|
||||
mouseActionUpdate(screenPos);
|
||||
|
||||
ClickHandlerPtr activated = ClickHandler::unpressed();
|
||||
auto pressedLinkItem = App::pressedLinkItem();
|
||||
auto activated = ClickHandler::unpressed();
|
||||
if (_mouseAction == MouseAction::Dragging) {
|
||||
activated.clear();
|
||||
} else if (auto pressed = App::pressedLinkItem()) {
|
||||
} else if (auto pressed = pressedLinkItem) {
|
||||
// if we are in selecting items mode perhaps we want to
|
||||
// toggle selection instead of activating the pressed link
|
||||
if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && !_selected.empty() && _selected.cbegin()->second == FullSelection && button != Qt::RightButton) {
|
||||
|
@ -2249,23 +2250,21 @@ void HistoryInner::onUpdateSelected() {
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryInner::updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dragSelTo, bool dragSelecting, bool force) {
|
||||
if (_dragSelFrom != dragSelFrom || _dragSelTo != dragSelTo || _dragSelecting != dragSelecting) {
|
||||
_dragSelFrom = dragSelFrom;
|
||||
_dragSelTo = dragSelTo;
|
||||
int32 fromy = itemTop(_dragSelFrom), toy = itemTop(_dragSelTo);
|
||||
if (fromy >= 0 && toy >= 0 && fromy > toy) {
|
||||
qSwap(_dragSelFrom, _dragSelTo);
|
||||
}
|
||||
_dragSelecting = dragSelecting;
|
||||
if (!_wasSelectedText && _dragSelFrom && _dragSelTo && _dragSelecting) {
|
||||
_wasSelectedText = true;
|
||||
setFocus();
|
||||
}
|
||||
force = true;
|
||||
void HistoryInner::updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dragSelTo, bool dragSelecting) {
|
||||
if (_dragSelFrom == dragSelFrom && _dragSelTo == dragSelTo && _dragSelecting == dragSelecting) {
|
||||
return;
|
||||
}
|
||||
_dragSelFrom = dragSelFrom;
|
||||
_dragSelTo = dragSelTo;
|
||||
int32 fromy = itemTop(_dragSelFrom), toy = itemTop(_dragSelTo);
|
||||
if (fromy >= 0 && toy >= 0 && fromy > toy) {
|
||||
qSwap(_dragSelFrom, _dragSelTo);
|
||||
}
|
||||
_dragSelecting = dragSelecting;
|
||||
if (!_wasSelectedText && _dragSelFrom && _dragSelTo && _dragSelecting) {
|
||||
_wasSelectedText = true;
|
||||
setFocus();
|
||||
}
|
||||
if (!force) return;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ private:
|
|||
void adjustCurrent(int32 y, History *history) const;
|
||||
HistoryItem *prevItem(HistoryItem *item);
|
||||
HistoryItem *nextItem(HistoryItem *item);
|
||||
void updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dragSelTo, bool dragSelecting, bool force = false);
|
||||
void updateDragSelection(HistoryItem *dragSelFrom, HistoryItem *dragSelTo, bool dragSelecting);
|
||||
|
||||
void setToClipboard(const TextWithEntities &forClipboard, QClipboard::Mode mode = QClipboard::Clipboard);
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ struct HistoryTextState {
|
|||
symbol = state.symbol;
|
||||
return *this;
|
||||
}
|
||||
HistoryTextState(ClickHandlerPtr link) : link(link) {
|
||||
}
|
||||
HistoryCursorState cursor = HistoryDefaultCursorState;
|
||||
ClickHandlerPtr link;
|
||||
bool afterSymbol = false;
|
||||
|
@ -656,11 +658,15 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual HistoryTextState getState(QPoint point, HistoryStateRequest request) const WARN_UNUSED_RESULT = 0;
|
||||
[[nodiscard]] virtual HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const = 0;
|
||||
virtual void updatePressed(QPoint point) {
|
||||
}
|
||||
|
||||
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] virtual TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
|
||||
|
@ -1051,10 +1057,12 @@ protected:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TextSelection skipTextSelection(TextSelection selection) const WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection skipTextSelection(
|
||||
TextSelection selection) const {
|
||||
return internal::unshiftSelection(selection, _text);
|
||||
}
|
||||
TextSelection unskipTextSelection(TextSelection selection) const WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection unskipTextSelection(
|
||||
TextSelection selection) const {
|
||||
return internal::shiftSelection(selection, _text);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,27 +93,37 @@ public:
|
|||
|
||||
// if we are in selecting items mode perhaps we want to
|
||||
// toggle selection instead of activating the pressed link
|
||||
virtual bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const = 0;
|
||||
virtual bool toggleSelectionByHandlerClick(
|
||||
const ClickHandlerPtr &p) const = 0;
|
||||
|
||||
// if we press and drag on this media should we drag the item
|
||||
virtual bool dragItem() const WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] virtual bool dragItem() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] virtual TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
virtual bool consumeMessageText(const TextWithEntities &textWithEntities) WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] virtual bool consumeMessageText(
|
||||
const TextWithEntities &textWithEntities) {
|
||||
return false;
|
||||
}
|
||||
virtual uint16 fullSelectionLength() const WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] virtual uint16 fullSelectionLength() const {
|
||||
return 0;
|
||||
}
|
||||
TextSelection skipSelection(TextSelection selection) const WARN_UNUSED_RESULT {
|
||||
return internal::unshiftSelection(selection, fullSelectionLength());
|
||||
[[nodiscard]] TextSelection skipSelection(
|
||||
TextSelection selection) const {
|
||||
return internal::unshiftSelection(
|
||||
selection,
|
||||
fullSelectionLength());
|
||||
}
|
||||
TextSelection unskipSelection(TextSelection selection) const WARN_UNUSED_RESULT {
|
||||
return internal::shiftSelection(selection, fullSelectionLength());
|
||||
[[nodiscard]] TextSelection unskipSelection(
|
||||
TextSelection selection) const {
|
||||
return internal::shiftSelection(
|
||||
selection,
|
||||
fullSelectionLength());
|
||||
}
|
||||
|
||||
// if we press and drag this link should we drag the item
|
||||
|
|
|
@ -144,7 +144,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
uint16 fullSelectionLength() const override {
|
||||
|
@ -230,7 +232,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
uint16 fullSelectionLength() const override {
|
||||
|
@ -382,7 +386,9 @@ public:
|
|||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
void updatePressed(QPoint point) override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override {
|
||||
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
@ -495,7 +501,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
uint16 fullSelectionLength() const override {
|
||||
|
@ -795,7 +803,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
uint16 fullSelectionLength() const override {
|
||||
return _title.length() + _description.length();
|
||||
}
|
||||
|
@ -902,7 +912,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
uint16 fullSelectionLength() const override {
|
||||
return _title.length() + _description.length();
|
||||
}
|
||||
|
@ -1016,7 +1028,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
uint16 fullSelectionLength() const override {
|
||||
return _title.length() + _description.length();
|
||||
}
|
||||
|
@ -1102,7 +1116,9 @@ public:
|
|||
void draw(Painter &p, const QRect &r, TextSelection selection, TimeMs ms) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override;
|
||||
uint16 fullSelectionLength() const override {
|
||||
return _title.length() + _description.length();
|
||||
}
|
||||
|
|
|
@ -88,7 +88,9 @@ public:
|
|||
bool hasPoint(QPoint point) const override;
|
||||
HistoryTextState getState(QPoint point, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const override {
|
||||
return _text.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -66,6 +66,18 @@ public:
|
|||
rpl::producer<int> scrollToRequests() const {
|
||||
return _scrollToRequests.events();
|
||||
}
|
||||
struct SelectedItem {
|
||||
explicit SelectedItem(FullMsgId msgId) : msgId(msgId) {
|
||||
}
|
||||
|
||||
FullMsgId msgId;
|
||||
bool canDelete = false;
|
||||
bool canForward = false;
|
||||
};
|
||||
using SelectedItems = std::vector<SelectedItem>;
|
||||
rpl::producer<SelectedItems> selectedItemsValue() const {
|
||||
return _selectedItemsStream.events();
|
||||
}
|
||||
|
||||
~ListWidget();
|
||||
|
||||
|
@ -98,19 +110,51 @@ private:
|
|||
std::unique_ptr<BaseLayout> item;
|
||||
bool stale = false;
|
||||
};
|
||||
struct Context;
|
||||
class Section;
|
||||
struct FoundItem {
|
||||
not_null<BaseLayout*> layout;
|
||||
QRect geometry;
|
||||
bool exact = false;
|
||||
};
|
||||
struct SelectionData {
|
||||
explicit SelectionData(TextSelection text) : text(text) {
|
||||
}
|
||||
|
||||
TextSelection text;
|
||||
bool canDelete = false;
|
||||
bool canForward = false;
|
||||
};
|
||||
using SelectedMap = base::flat_map<
|
||||
UniversalMsgId,
|
||||
SelectionData,
|
||||
std::less<>>;
|
||||
enum class DragSelectAction {
|
||||
None,
|
||||
Selecting,
|
||||
Deselecting,
|
||||
};
|
||||
struct CursorState {
|
||||
UniversalMsgId itemId = 0;
|
||||
QSize size;
|
||||
QPoint cursor;
|
||||
bool inside = false;
|
||||
|
||||
inline bool operator==(const CursorState &other) const {
|
||||
return (itemId == other.itemId)
|
||||
&& (cursor == other.cursor);
|
||||
}
|
||||
inline bool operator!=(const CursorState &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void start();
|
||||
int recountHeight();
|
||||
void refreshHeight();
|
||||
|
||||
QMargins padding() const;
|
||||
void updateSelected();
|
||||
bool isMyItem(not_null<const HistoryItem*> item) const;
|
||||
bool isItemLayout(
|
||||
not_null<const HistoryItem*> item,
|
||||
|
@ -118,6 +162,7 @@ private:
|
|||
void repaintItem(const HistoryItem *item);
|
||||
void repaintItem(UniversalMsgId msgId);
|
||||
void repaintItem(const BaseLayout *item);
|
||||
void repaintItem(QRect itemGeometry);
|
||||
void itemRemoved(not_null<const HistoryItem*> item);
|
||||
void itemLayoutChanged(not_null<const HistoryItem*> item);
|
||||
|
||||
|
@ -126,12 +171,46 @@ private:
|
|||
void refreshRows();
|
||||
SharedMediaMergedSlice::Key sliceKey(
|
||||
UniversalMsgId universalId) const;
|
||||
BaseLayout *getLayout(const FullMsgId &itemId);
|
||||
BaseLayout *getExistingLayout(const FullMsgId &itemId) const;
|
||||
BaseLayout *getLayout(UniversalMsgId universalId);
|
||||
BaseLayout *getExistingLayout(UniversalMsgId universalId) const;
|
||||
std::unique_ptr<BaseLayout> createLayout(
|
||||
const FullMsgId &itemId,
|
||||
UniversalMsgId universalId,
|
||||
Type type);
|
||||
|
||||
SelectedItems collectSelectedItems() const;
|
||||
void pushSelectedItems();
|
||||
FullMsgId computeFullId(UniversalMsgId universalId) const;
|
||||
bool hasSelected() const;
|
||||
bool isSelectedItem(
|
||||
const SelectedMap::const_iterator &i) const;
|
||||
void removeItemSelection(
|
||||
const SelectedMap::const_iterator &i);
|
||||
bool hasSelectedText() const;
|
||||
bool hasSelectedItems() const;
|
||||
void clearSelected();
|
||||
void applyItemSelection(
|
||||
UniversalMsgId universalId,
|
||||
TextSelection selection);
|
||||
void toggleItemSelection(
|
||||
UniversalMsgId universalId);
|
||||
SelectedMap::iterator itemUnderPressSelection();
|
||||
SelectedMap::const_iterator itemUnderPressSelection() const;
|
||||
bool isItemUnderPressSelected() const;
|
||||
bool requiredToStartDragging(not_null<BaseLayout*> layout) const;
|
||||
bool isPressInSelectedText(HistoryTextState state) const;
|
||||
void applyDragSelection();
|
||||
void applyDragSelection(SelectedMap &applyTo) const;
|
||||
bool changeItemSelection(
|
||||
SelectedMap &selected,
|
||||
UniversalMsgId universalId,
|
||||
TextSelection selection) const;
|
||||
|
||||
static bool IsAfter(
|
||||
const CursorState &a,
|
||||
const CursorState &b);
|
||||
static bool SkipSelectFromItem(const CursorState &state);
|
||||
static bool SkipSelectTillItem(const CursorState &state);
|
||||
|
||||
void markLayoutsStale();
|
||||
void clearStaleLayouts();
|
||||
std::vector<Section>::iterator findSectionByItem(
|
||||
|
@ -157,11 +236,25 @@ private:
|
|||
const QPoint &screenPos,
|
||||
Qt::MouseButton button);
|
||||
void mouseActionUpdate(const QPoint &screenPos);
|
||||
void mouseActionUpdate();
|
||||
void mouseActionFinish(
|
||||
const QPoint &screenPos,
|
||||
Qt::MouseButton button);
|
||||
void mouseActionCancel();
|
||||
void performDrag();
|
||||
style::cursor computeMouseCursor() const;
|
||||
|
||||
void updateDragSelection();
|
||||
void clearDragSelection();
|
||||
void setDragSelection(
|
||||
BaseLayout *dragSelectFrom,
|
||||
BaseLayout *dragSelectTill,
|
||||
DragSelectAction action);
|
||||
|
||||
void trySwitchToWordSelection();
|
||||
void switchToWordSelection();
|
||||
void validateTrippleClickStartTime();
|
||||
void checkMoveToOtherViewer();
|
||||
|
||||
not_null<Window::Controller*> _controller;
|
||||
not_null<PeerData*> _peer;
|
||||
|
@ -183,29 +276,24 @@ private:
|
|||
|
||||
MouseAction _mouseAction = MouseAction::None;
|
||||
TextSelectType _mouseSelectType = TextSelectType::Letters;
|
||||
QPoint _dragStartPosition;
|
||||
QPoint _mousePosition;
|
||||
BaseLayout *_itemNearestToCursor = nullptr;
|
||||
BaseLayout *_itemUnderCursor = nullptr;
|
||||
BaseLayout *_itemUnderPress = nullptr;
|
||||
CursorState _overState;
|
||||
CursorState _pressState;
|
||||
BaseLayout *_overLayout = nullptr;
|
||||
HistoryCursorState _mouseCursorState = HistoryDefaultCursorState;
|
||||
// uint16 _mouseTextSymbol = 0;
|
||||
uint16 _mouseTextSymbol = 0;
|
||||
bool _pressWasInactive = false;
|
||||
using SelectedItems = std::map<
|
||||
UniversalMsgId,
|
||||
TextSelection,
|
||||
std::less<>>;
|
||||
SelectedItems _selected;
|
||||
SelectedMap _selected;
|
||||
SelectedMap _dragSelected;
|
||||
rpl::event_stream<SelectedItems> _selectedItemsStream;
|
||||
style::cursor _cursor = style::cur_default;
|
||||
BaseLayout *_dragSelFrom = nullptr;
|
||||
BaseLayout *_dragSelTo = nullptr;
|
||||
// bool _dragSelecting = false;
|
||||
DragSelectAction _dragSelectAction = DragSelectAction::None;
|
||||
bool _wasSelectedText = false; // was some text selected in current drag action
|
||||
Ui::PopupMenu *_contextMenu = nullptr;
|
||||
ClickHandlerPtr _contextMenuLink;
|
||||
|
||||
QPoint _trippleClickPoint;
|
||||
QTimer _trippleClickTimer;
|
||||
TimeMs _trippleClickStartTime = 0;
|
||||
|
||||
rpl::lifetime _viewerLifetime;
|
||||
|
||||
|
|
|
@ -213,14 +213,17 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
|
|||
}
|
||||
}
|
||||
|
||||
void Gif::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Gif::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) {
|
||||
if (_delete && rtlpoint(point, _width).x() >= _width - st::stickerPanDeleteIconBg.width() && point.y() < st::stickerPanDeleteIconBg.height()) {
|
||||
link = _delete;
|
||||
return _delete;
|
||||
} else {
|
||||
link = _send;
|
||||
return _send;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Gif::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||
|
@ -404,10 +407,13 @@ void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
void Sticker::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Sticker::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) {
|
||||
link = _send;
|
||||
return _send;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Sticker::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||
|
@ -491,10 +497,13 @@ void Photo::paint(Painter &p, const QRect &clip, const PaintContext *context) co
|
|||
}
|
||||
}
|
||||
|
||||
void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Photo::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (QRect(0, 0, _width, st::inlineMediaHeight).contains(point)) {
|
||||
link = _send;
|
||||
return _send;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
PhotoData *Photo::getShownPhoto() const {
|
||||
|
@ -633,15 +642,16 @@ void Video::paint(Painter &p, const QRect &clip, const PaintContext *context) co
|
|||
}
|
||||
}
|
||||
|
||||
void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Video::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) {
|
||||
link = _link;
|
||||
return;
|
||||
return _link;
|
||||
}
|
||||
if (QRect(st::inlineThumbSize + st::inlineThumbSkip, 0, _width - st::inlineThumbSize - st::inlineThumbSkip, _height).contains(point)) {
|
||||
link = _send;
|
||||
return;
|
||||
return _send;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Video::prepareThumb(int32 width, int32 height) const {
|
||||
|
@ -773,16 +783,18 @@ void File::paint(Painter &p, const QRect &clip, const PaintContext *context) con
|
|||
}
|
||||
}
|
||||
|
||||
void File::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState File::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (QRect(0, st::inlineRowMargin, st::msgFileSize, st::msgFileSize).contains(point)) {
|
||||
link = getShownDocument()->loading() ? _cancel : _open;
|
||||
return;
|
||||
}
|
||||
auto left = st::msgFileSize + st::inlineThumbSkip;
|
||||
if (QRect(left, 0, _width - left, _height).contains(point)) {
|
||||
link = _send;
|
||||
return;
|
||||
return getShownDocument()->loading() ? _cancel : _open;
|
||||
} else {
|
||||
auto left = st::msgFileSize + st::inlineThumbSkip;
|
||||
if (QRect(left, 0, _width - left, _height).contains(point)) {
|
||||
return _send;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void File::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||
|
@ -933,15 +945,16 @@ void Contact::paint(Painter &p, const QRect &clip, const PaintContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
void Contact::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
if (QRect(0, st::inlineRowMargin, st::msgFileSize, st::inlineThumbSize).contains(point)) {
|
||||
return;
|
||||
}
|
||||
auto left = (st::msgFileSize + st::inlineThumbSkip);
|
||||
if (QRect(left, 0, _width - left, _height).contains(point)) {
|
||||
link = _send;
|
||||
return;
|
||||
HistoryTextState Contact::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (!QRect(0, st::inlineRowMargin, st::msgFileSize, st::inlineThumbSize).contains(point)) {
|
||||
auto left = (st::msgFileSize + st::inlineThumbSkip);
|
||||
if (QRect(left, 0, _width - left, _height).contains(point)) {
|
||||
return _send;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Contact::prepareThumb(int width, int height) const {
|
||||
|
@ -1069,10 +1082,11 @@ void Article::paint(Painter &p, const QRect &clip, const PaintContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
void Article::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Article::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (_withThumb && QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) {
|
||||
link = _link;
|
||||
return;
|
||||
return _link;
|
||||
}
|
||||
auto left = _withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0;
|
||||
if (QRect(left, 0, _width - left, _height).contains(point)) {
|
||||
|
@ -1082,13 +1096,12 @@ void Article::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint
|
|||
auto descriptionLines = 2;
|
||||
auto descriptionHeight = qMin(_description.countHeight(_width - left), st::normalFont->height * descriptionLines);
|
||||
if (rtlrect(left, st::inlineRowMargin + titleHeight + descriptionHeight, _urlWidth, st::normalFont->height, _width).contains(point)) {
|
||||
link = _url;
|
||||
return;
|
||||
return _url;
|
||||
}
|
||||
}
|
||||
link = _send;
|
||||
return;
|
||||
return _send;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Article::prepareThumb(int width, int height) const {
|
||||
|
@ -1253,16 +1266,17 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con
|
|||
}
|
||||
}
|
||||
|
||||
void Game::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Game::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
int left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||
if (QRect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize).contains(point)) {
|
||||
link = _send;
|
||||
return;
|
||||
return _send;
|
||||
}
|
||||
if (QRect(left, 0, _width - left, _height).contains(point)) {
|
||||
link = _send;
|
||||
return;
|
||||
return _send;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Game::prepareThumb(int width, int height) const {
|
||||
|
|
|
@ -73,7 +73,9 @@ public:
|
|||
}
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
@ -130,7 +132,9 @@ public:
|
|||
}
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
private:
|
||||
PhotoData *getShownPhoto() const;
|
||||
|
@ -160,7 +164,9 @@ public:
|
|||
void preload() const override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
@ -184,7 +190,9 @@ public:
|
|||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
private:
|
||||
ClickHandlerPtr _link;
|
||||
|
@ -231,7 +239,9 @@ public:
|
|||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
|
||||
|
@ -294,7 +304,9 @@ public:
|
|||
int resizeGetHeight(int width) override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
private:
|
||||
mutable QPixmap _thumb;
|
||||
|
@ -312,7 +324,9 @@ public:
|
|||
int resizeGetHeight(int width) override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
private:
|
||||
ClickHandlerPtr _url, _link;
|
||||
|
@ -335,7 +349,9 @@ public:
|
|||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
private:
|
||||
void countFrameSize();
|
||||
|
|
|
@ -644,8 +644,10 @@ void Inner::updateSelected() {
|
|||
}
|
||||
if (col < inlineItems.size()) {
|
||||
sel = row * MatrixRowShift + col;
|
||||
inlineItems.at(col)->getState(lnk, cursor, QPoint(sx, sy));
|
||||
lnkhost = inlineItems.at(col);
|
||||
auto result = inlineItems[col]->getState(QPoint(sx, sy), HistoryStateRequest());
|
||||
lnk = result.link;
|
||||
cursor = result.cursor;
|
||||
lnkhost = inlineItems[col];
|
||||
} else {
|
||||
row = col = -1;
|
||||
}
|
||||
|
|
|
@ -119,14 +119,15 @@ public:
|
|||
return _height;
|
||||
}
|
||||
|
||||
virtual void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
link.clear();
|
||||
cursor = HistoryDefaultCursorState;
|
||||
[[nodiscard]] virtual HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
return {};
|
||||
}
|
||||
virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, QPoint point) const { // from text
|
||||
upon = hasPoint(point);
|
||||
symbol = upon ? 0xFFFF : 0;
|
||||
after = false;
|
||||
[[nodiscard]] virtual TextSelection adjustSelection(
|
||||
TextSelection selection,
|
||||
TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
|
||||
int width() const {
|
||||
|
|
|
@ -104,7 +104,9 @@ void ListWidget::mouseMoveEvent(QMouseEvent *e) {
|
|||
if (y <= m.y()) {
|
||||
if (auto media = layout->toMediaItem()) {
|
||||
item = media->getItem();
|
||||
media->getState(lnk, cursorState, m - QPoint(0, y));
|
||||
auto result = media->getState(m - QPoint(0, y), HistoryStateRequest());
|
||||
lnk = result.link;
|
||||
cursorState = result.cursor;
|
||||
lnkhost = media;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1153,7 +1153,11 @@ void MediaView::refreshMediaViewer() {
|
|||
}
|
||||
|
||||
void MediaView::showPhoto(not_null<PhotoData*> photo, HistoryItem *context) {
|
||||
setContext(context);
|
||||
if (context) {
|
||||
setContext(context);
|
||||
} else {
|
||||
setContext(base::none);
|
||||
}
|
||||
|
||||
_firstOpenedPeerPhoto = false;
|
||||
_saveMsgStarted = 0;
|
||||
|
|
|
@ -214,39 +214,39 @@ public:
|
|||
SpecificRequestBuilder(SpecificRequestBuilder &&other) = default;
|
||||
|
||||
public:
|
||||
SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &toDC(ShiftedDcId dcId) noexcept {
|
||||
setToDC(dcId);
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &canWait(TimeMs ms) noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &canWait(TimeMs ms) noexcept {
|
||||
setCanWait(ms);
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &done(base::lambda_once<void(const typename Request::ResponseType &result)> callback) WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &done(base::lambda_once<void(const typename Request::ResponseType &result)> callback) {
|
||||
setDoneHandler(MakeShared<DoneHandler<typename Request::ResponseType, DonePlainPolicy>>(sender(), std::move(callback)));
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &done(base::lambda_once<void(const typename Request::ResponseType &result, mtpRequestId requestId)> callback) WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &done(base::lambda_once<void(const typename Request::ResponseType &result, mtpRequestId requestId)> callback) {
|
||||
setDoneHandler(MakeShared<DoneHandler<typename Request::ResponseType, DoneRequestIdPolicy>>(sender(), std::move(callback)));
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &fail(base::lambda_once<void(const RPCError &error)> callback) noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &fail(base::lambda_once<void(const RPCError &error)> callback) noexcept {
|
||||
setFailHandler(std::move(callback));
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &fail(base::lambda_once<void(const RPCError &error, mtpRequestId requestId)> callback) noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &fail(base::lambda_once<void(const RPCError &error, mtpRequestId requestId)> callback) noexcept {
|
||||
setFailHandler(std::move(callback));
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &handleFloodErrors() noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &handleFloodErrors() noexcept {
|
||||
setFailSkipPolicy(FailSkipPolicy::HandleFlood);
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &handleAllErrors() noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &handleAllErrors() noexcept {
|
||||
setFailSkipPolicy(FailSkipPolicy::HandleAll);
|
||||
return *this;
|
||||
}
|
||||
SpecificRequestBuilder &after(mtpRequestId requestId) noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] SpecificRequestBuilder &after(mtpRequestId requestId) noexcept {
|
||||
setAfter(requestId);
|
||||
return *this;
|
||||
}
|
||||
|
@ -280,11 +280,11 @@ public:
|
|||
};
|
||||
|
||||
template <typename Request, typename = std::enable_if_t<std::is_rvalue_reference<Request&&>::value>, typename = typename Request::Unboxed>
|
||||
SpecificRequestBuilder<Request> request(Request &&request) noexcept WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] SpecificRequestBuilder<Request> request(Request &&request) noexcept;
|
||||
|
||||
SentRequestWrap request(mtpRequestId requestId) noexcept WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] SentRequestWrap request(mtpRequestId requestId) noexcept;
|
||||
|
||||
decltype(auto) requestCanceller() noexcept WARN_UNUSED_RESULT {
|
||||
[[nodiscard]] decltype(auto) requestCanceller() noexcept {
|
||||
return [this](mtpRequestId requestId) {
|
||||
request(requestId).cancel();
|
||||
};
|
||||
|
|
|
@ -66,12 +66,16 @@ TextWithEntities ComposeNameWithEntities(DocumentData *document) {
|
|||
|
||||
} // namespace
|
||||
|
||||
void ItemBase::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||
void ItemBase::clickHandlerActiveChanged(
|
||||
const ClickHandlerPtr &action,
|
||||
bool active) {
|
||||
App::hoveredLinkItem(active ? _parent.get() : nullptr);
|
||||
Auth().data().requestItemRepaint(_parent);
|
||||
}
|
||||
|
||||
void ItemBase::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
|
||||
void ItemBase::clickHandlerPressedChanged(
|
||||
const ClickHandlerPtr &action,
|
||||
bool pressed) {
|
||||
App::pressedLinkItem(pressed ? _parent.get() : nullptr);
|
||||
Auth().data().requestItemRepaint(_parent);
|
||||
}
|
||||
|
@ -306,10 +310,13 @@ void Photo::ensureCheckboxCreated() {
|
|||
});
|
||||
}
|
||||
|
||||
void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Photo::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
if (hasPoint(point)) {
|
||||
link = _link;
|
||||
return _link;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Photo::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||
|
@ -506,12 +513,15 @@ bool Video::iconAnimated() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Video::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
bool loaded = _data->loaded();
|
||||
|
||||
if (hasPoint(point)) {
|
||||
link = loaded ? _openl : (_data->loading() ? _cancell : _savel);
|
||||
return loaded ? _openl : (_data->loading() ? _cancell : _savel);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Video::updateStatusText() {
|
||||
|
@ -664,7 +674,9 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
|
|||
}
|
||||
}
|
||||
|
||||
void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Voice::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
bool loaded = _data->loaded();
|
||||
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
|
||||
|
@ -676,20 +688,20 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint p
|
|||
|
||||
auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width);
|
||||
if (inner.contains(point)) {
|
||||
link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
|
||||
return;
|
||||
return loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
|
||||
}
|
||||
auto result = HistoryTextState();
|
||||
if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(point)) {
|
||||
if (_status.size() == FileStatusSizeLoaded || _status.size() == FileStatusSizeReady) {
|
||||
auto textState = _details.getStateLeft(point - QPoint(nameleft, statustop), _width, _width);
|
||||
link = textState.link;
|
||||
cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
result.link = textState.link;
|
||||
result.cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
}
|
||||
}
|
||||
if (hasPoint(point) && !link && !_data->loading()) {
|
||||
link = _namel;
|
||||
return;
|
||||
if (hasPoint(point) && !result.link && !_data->loading()) {
|
||||
return _namel;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float64 Voice::dataProgress() const {
|
||||
|
@ -954,7 +966,9 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
|
|||
}
|
||||
}
|
||||
|
||||
void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Document::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey());
|
||||
|
||||
int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
|
||||
|
@ -968,12 +982,10 @@ void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoin
|
|||
|
||||
auto inner = rtlrect(_st.songPadding.left(), _st.songPadding.top(), _st.songThumbSize, _st.songThumbSize, _width);
|
||||
if (inner.contains(point)) {
|
||||
link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
|
||||
return;
|
||||
return loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _openl);
|
||||
}
|
||||
if (hasPoint(point) && !_data->loading()) {
|
||||
link = _namel;
|
||||
return;
|
||||
return _namel;
|
||||
}
|
||||
} else {
|
||||
nameleft = _st.fileThumbSize + _st.filePadding.right();
|
||||
|
@ -984,27 +996,24 @@ void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoin
|
|||
auto rthumb = rtlrect(0, st::linksBorder + _st.filePadding.top(), _st.fileThumbSize, _st.fileThumbSize, _width);
|
||||
|
||||
if (rthumb.contains(point)) {
|
||||
link = loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _savel);
|
||||
return;
|
||||
return loaded ? _openl : ((_data->loading() || _data->status == FileUploading) ? _cancell : _savel);
|
||||
}
|
||||
|
||||
if (_data->status != FileUploadFailed) {
|
||||
if (rtlrect(nameleft, datetop, _datew, st::normalFont->height, _width).contains(point)) {
|
||||
link = _msgl;
|
||||
return;
|
||||
return _msgl;
|
||||
}
|
||||
}
|
||||
if (!_data->loading() && _data->isValid()) {
|
||||
if (loaded && rtlrect(0, st::linksBorder, nameleft, _height - st::linksBorder, _width).contains(point)) {
|
||||
link = _namel;
|
||||
return;
|
||||
return _namel;
|
||||
}
|
||||
if (rtlrect(nameleft, nametop, qMin(_width - nameleft - nameright, _name.maxWidth()), st::semiboldFont->height, _width).contains(point)) {
|
||||
link = _namel;
|
||||
return;
|
||||
return _namel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
float64 Document::dataProgress() const {
|
||||
|
@ -1301,11 +1310,12 @@ void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const P
|
|||
}
|
||||
}
|
||||
|
||||
void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const {
|
||||
HistoryTextState Link::getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const {
|
||||
int32 left = st::linksPhotoSize + st::linksPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
|
||||
if (rtlrect(0, top, st::linksPhotoSize, st::linksPhotoSize, _width).contains(point)) {
|
||||
link = _photol;
|
||||
return;
|
||||
return _photol;
|
||||
}
|
||||
|
||||
if (!_title.isEmpty() && _text.isEmpty() && _links.size() == 1) {
|
||||
|
@ -1313,8 +1323,7 @@ void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint po
|
|||
}
|
||||
if (!_title.isEmpty()) {
|
||||
if (rtlrect(left, top, qMin(w, _titlew), st::semiboldFont->height, _width).contains(point)) {
|
||||
link = _photol;
|
||||
return;
|
||||
return _photol;
|
||||
}
|
||||
top += st::webPageTitleFont->height;
|
||||
}
|
||||
|
@ -1323,11 +1332,11 @@ void Link::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint po
|
|||
}
|
||||
for (int32 i = 0, l = _links.size(); i < l; ++i) {
|
||||
if (rtlrect(left, top, qMin(w, _links.at(i).width), st::normalFont->height, _width).contains(point)) {
|
||||
link = _links.at(i).lnk;
|
||||
return;
|
||||
return _links.at(i).lnk;
|
||||
}
|
||||
top += st::normalFont->height;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Link::LinkEntry::LinkEntry(const QString &url, const QString &text)
|
||||
|
|
|
@ -189,7 +189,9 @@ public:
|
|||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
||||
|
@ -220,7 +222,9 @@ public:
|
|||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
||||
|
@ -260,7 +264,9 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
protected:
|
||||
float64 dataProgress() const override;
|
||||
|
@ -292,7 +298,9 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
virtual DocumentData *getDocument() const override {
|
||||
return _data;
|
||||
|
@ -333,7 +341,9 @@ public:
|
|||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, QPoint point) const override;
|
||||
HistoryTextState getState(
|
||||
QPoint point,
|
||||
HistoryStateRequest request) const override;
|
||||
|
||||
private:
|
||||
ClickHandlerPtr _photol;
|
||||
|
|
|
@ -900,7 +900,9 @@ void OverviewInner::onUpdateSelected() {
|
|||
item = media->getItem();
|
||||
index = i;
|
||||
if (upon) {
|
||||
media->getState(lnk, cursorState, m - QPoint(col * w + st::overviewPhotoSkip, _marginTop + row * vsize + st::overviewPhotoSkip));
|
||||
auto result = media->getState(m - QPoint(col * w + st::overviewPhotoSkip, _marginTop + row * vsize + st::overviewPhotoSkip), HistoryStateRequest());
|
||||
lnk = result.link;
|
||||
cursorState = result.cursor;
|
||||
lnkhost = media;
|
||||
}
|
||||
}
|
||||
|
@ -936,7 +938,9 @@ void OverviewInner::onUpdateSelected() {
|
|||
if (auto media = _items.at(i)->toMediaItem()) {
|
||||
item = media->getItem();
|
||||
index = i;
|
||||
media->getState(lnk, cursorState, m - QPoint(_rowsLeft, _marginTop + top));
|
||||
auto result = media->getState(m - QPoint(_rowsLeft, _marginTop + top), HistoryStateRequest());
|
||||
lnk = result.link;
|
||||
cursorState = result.cursor;
|
||||
lnkhost = media;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -165,7 +165,7 @@ public:
|
|||
return getStateElided(rtlpoint(point, outerw), width, request);
|
||||
}
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType selectType) const WARN_UNUSED_RESULT;
|
||||
[[nodiscard]] TextSelection adjustSelection(TextSelection selection, TextSelectType selectType) const;
|
||||
bool isFullSelection(TextSelection selection) const {
|
||||
return (selection.from == 0) && (selection.to >= _text.size());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue