mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Selection of text in attachments: captions, web page previews.
Text/HistoryItem/HistoryMedia::getState() unified. Text::getStateElided added. Tested with web page previews only.
This commit is contained in:
parent
a033e31743
commit
c4a7d48d96
19 changed files with 815 additions and 674 deletions
|
@ -119,10 +119,10 @@ void ConfirmBox::updateHover() {
|
|||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
|
||||
textstyleSet(&st::boxTextStyle);
|
||||
ClickHandlerPtr handler = _text.linkLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width(), style::al_left);
|
||||
auto state = _text.getStateLeft(m.x() - st::boxPadding.left(), m.y() - st::boxPadding.top(), _textWidth, width());
|
||||
textstyleRestore();
|
||||
|
||||
ClickHandler::setActive(handler, this);
|
||||
ClickHandler::setActive(state.link, this);
|
||||
}
|
||||
|
||||
void ConfirmBox::closePressed() {
|
||||
|
|
|
@ -1349,7 +1349,7 @@ void StickerPanInner::paintInlineItems(Painter &p, const QRect &r) {
|
|||
int w = item->width();
|
||||
if (left + w > fromx) {
|
||||
p.translate(left, top);
|
||||
item->paint(p, r.translated(-left, -top), 0, &context);
|
||||
item->paint(p, r.translated(-left, -top), &context);
|
||||
p.translate(-left, -top);
|
||||
}
|
||||
left += w;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -729,7 +729,7 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
class HistoryMessage; // dynamic_cast optimize
|
||||
class HistoryMessage;
|
||||
|
||||
enum HistoryCursorState {
|
||||
HistoryDefaultCursorState,
|
||||
|
@ -738,6 +738,36 @@ enum HistoryCursorState {
|
|||
HistoryInForwardedCursorState,
|
||||
};
|
||||
|
||||
struct HistoryTextState {
|
||||
HistoryTextState() = default;
|
||||
HistoryTextState(const Text::StateResult &state)
|
||||
: cursor(state.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState)
|
||||
, link(state.link)
|
||||
, afterSymbol(state.afterSymbol)
|
||||
, symbol(state.symbol) {
|
||||
}
|
||||
HistoryTextState &operator=(const Text::StateResult &state) {
|
||||
cursor = state.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
link = state.link;
|
||||
afterSymbol = state.afterSymbol;
|
||||
symbol = state.symbol;
|
||||
return *this;
|
||||
}
|
||||
HistoryCursorState cursor = HistoryDefaultCursorState;
|
||||
ClickHandlerPtr link;
|
||||
bool afterSymbol = false;
|
||||
uint16 symbol = 0;
|
||||
};
|
||||
|
||||
struct HistoryStateRequest {
|
||||
Text::StateRequest::Flags flags = Text::StateRequest::Flag::LookupLink;
|
||||
Text::StateRequest forText() const {
|
||||
Text::StateRequest result;
|
||||
result.flags = flags;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
enum InfoDisplayType {
|
||||
InfoDisplayDefault,
|
||||
InfoDisplayOverImage,
|
||||
|
@ -936,7 +966,7 @@ public:
|
|||
int naturalHeight() const;
|
||||
|
||||
void paint(Painter &p, const QRect &clip) const;
|
||||
void getState(ClickHandlerPtr &lnk, int x, int y) const;
|
||||
ClickHandlerPtr getState(int x, int y) const;
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed);
|
||||
|
@ -1068,7 +1098,7 @@ public:
|
|||
}
|
||||
return resizeGetHeight_(width);
|
||||
}
|
||||
virtual void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const = 0;
|
||||
virtual void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const = 0;
|
||||
|
||||
virtual void dependencyItemRemoved(HistoryItem *dependency) {
|
||||
}
|
||||
|
@ -1216,17 +1246,11 @@ public:
|
|||
virtual bool hasPoint(int x, int y) const {
|
||||
return false;
|
||||
}
|
||||
virtual void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const {
|
||||
lnk.clear();
|
||||
state = HistoryDefaultCursorState;
|
||||
}
|
||||
virtual void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const { // from text
|
||||
upon = hasPoint(x, y);
|
||||
symbol = upon ? 0xFFFF : 0;
|
||||
after = false;
|
||||
}
|
||||
virtual uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const {
|
||||
return (from << 16) | to;
|
||||
|
||||
virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0;
|
||||
|
||||
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
|
||||
// ClickHandlerHost interface
|
||||
|
@ -1251,7 +1275,7 @@ public:
|
|||
}
|
||||
virtual void previousItemChanged();
|
||||
|
||||
virtual QString selectedText(uint32 selection) const {
|
||||
virtual QString selectedText(TextSelection selection) const {
|
||||
return qsl("[-]");
|
||||
}
|
||||
virtual QString inDialogsText() const {
|
||||
|
@ -1514,6 +1538,13 @@ protected:
|
|||
return const_cast<ReplyKeyboard*>(static_cast<const HistoryItem*>(this)->inlineReplyKeyboard());
|
||||
}
|
||||
|
||||
TextSelection toMediaSelection(TextSelection selection) const {
|
||||
return unshiftSelection(selection, _text);
|
||||
}
|
||||
TextSelection fromMediaSelection(TextSelection selection) const {
|
||||
return shiftSelection(selection, _text);
|
||||
}
|
||||
|
||||
Text _text = { int(st::msgMinWidth) };
|
||||
int32 _textWidth, _textHeight;
|
||||
|
||||
|
@ -1624,8 +1655,8 @@ public:
|
|||
_width = qMin(width, _maxw);
|
||||
return _height;
|
||||
}
|
||||
virtual void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const = 0;
|
||||
virtual void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const = 0;
|
||||
virtual void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const = 0;
|
||||
virtual HistoryTextState getState(int x, int y, HistoryStateRequest request) const = 0;
|
||||
|
||||
// if we are in selecting items mode perhaps we want to
|
||||
// toggle selection instead of activating the pressed link
|
||||
|
@ -1636,6 +1667,10 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual TextSelection adjustSelection(TextSelection selection, TextSelectType type) const {
|
||||
return selection;
|
||||
}
|
||||
|
||||
// if we press and drag this link should we drag the item
|
||||
virtual bool dragItemByHandler(const ClickHandlerPtr &p) const = 0;
|
||||
|
||||
|
@ -1829,8 +1864,12 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
|
@ -1902,8 +1941,12 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
|
@ -2015,8 +2058,15 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
|
||||
return captioned->_caption.adjustSelection(selection, type);
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
|
@ -2095,8 +2145,12 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _caption.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
const QString inDialogsText() const override;
|
||||
const QString inHistoryText() const override;
|
||||
|
@ -2183,8 +2237,8 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
|
@ -2255,8 +2309,8 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return true;
|
||||
|
@ -2318,8 +2372,10 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return _attach && _attach->toggleSelectionByHandlerClick(p);
|
||||
|
@ -2376,6 +2432,13 @@ public:
|
|||
~HistoryWebPage();
|
||||
|
||||
private:
|
||||
TextSelection toDescriptionSelection(TextSelection selection) const {
|
||||
return unshiftSelection(selection, _title);
|
||||
}
|
||||
TextSelection fromDescriptionSelection(TextSelection selection) const {
|
||||
return shiftSelection(selection, _title);
|
||||
}
|
||||
|
||||
WebPageData *_data;
|
||||
ClickHandlerPtr _openl;
|
||||
HistoryMedia *_attach;
|
||||
|
@ -2440,8 +2503,10 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int32 width) override;
|
||||
|
||||
void draw(Painter &p, const QRect &r, bool selected, uint64 ms) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
|
||||
|
||||
bool toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const override {
|
||||
return p == _link;
|
||||
|
@ -2467,6 +2532,13 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
TextSelection toDescriptionSelection(TextSelection selection) const {
|
||||
return unshiftSelection(selection, _title);
|
||||
}
|
||||
TextSelection fromDescriptionSelection(TextSelection selection) const {
|
||||
return shiftSelection(selection, _title);
|
||||
}
|
||||
|
||||
LocationData *_data;
|
||||
Text _title, _description;
|
||||
ClickHandlerPtr _link;
|
||||
|
@ -2538,7 +2610,7 @@ public:
|
|||
void drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const override;
|
||||
void setViewsCount(int32 count) override;
|
||||
void setId(MsgId newId) override;
|
||||
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
|
||||
void dependencyItemRemoved(HistoryItem *dependency) override;
|
||||
|
||||
|
@ -2547,12 +2619,9 @@ public:
|
|||
bool hasPoint(int x, int y) const override;
|
||||
bool pointInTime(int32 right, int32 bottom, int x, int y, InfoDisplayType type) const override;
|
||||
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const override;
|
||||
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const override {
|
||||
return _text.adjustSelection(from, to, type);
|
||||
}
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override {
|
||||
|
@ -2573,7 +2642,7 @@ public:
|
|||
int32 addToOverview(AddToOverviewMethod method) override;
|
||||
void eraseFromOverview();
|
||||
|
||||
QString selectedText(uint32 selection) const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
QString inDialogsText() const override;
|
||||
HistoryMedia *getMedia() const override;
|
||||
void setText(const QString &text, const EntitiesInText &entities) override;
|
||||
|
@ -2763,12 +2832,12 @@ public:
|
|||
|
||||
void countPositionAndSize(int32 &left, int32 &width) const;
|
||||
|
||||
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const override;
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const override;
|
||||
bool hasPoint(int x, int y) const override;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const override;
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const override;
|
||||
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType type) const override {
|
||||
return _text.adjustSelection(from, to, type);
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const override;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType type) const override {
|
||||
return _text.adjustSelection(selection, type);
|
||||
}
|
||||
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override {
|
||||
|
@ -2789,7 +2858,7 @@ public:
|
|||
bool serviceMsg() const override {
|
||||
return true;
|
||||
}
|
||||
QString selectedText(uint32 selection) const override;
|
||||
QString selectedText(TextSelection selection) const override;
|
||||
QString inDialogsText() const override;
|
||||
QString inReplyText() const override;
|
||||
|
||||
|
@ -2824,12 +2893,8 @@ public:
|
|||
return _create(history, newItem, date);
|
||||
}
|
||||
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const;
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const {
|
||||
symbol = 0xFFFF;
|
||||
after = false;
|
||||
upon = false;
|
||||
}
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const;
|
||||
|
||||
QString selectedText(uint32 selection) const {
|
||||
return QString();
|
||||
}
|
||||
|
@ -2877,13 +2942,9 @@ public:
|
|||
return _create(history, wasMinId, date);
|
||||
}
|
||||
|
||||
void draw(Painter &p, const QRect &r, uint32 selection, uint64 ms) const;
|
||||
void getState(ClickHandlerPtr &lnk, HistoryCursorState &state, int x, int y) const;
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int x, int y) const {
|
||||
symbol = 0xFFFF;
|
||||
after = false;
|
||||
upon = false;
|
||||
}
|
||||
void draw(Painter &p, const QRect &r, TextSelection selection, uint64 ms) const;
|
||||
HistoryTextState getState(int x, int y, HistoryStateRequest request) const;
|
||||
|
||||
QString selectedText(uint32 selection) const {
|
||||
return QString();
|
||||
}
|
||||
|
|
|
@ -252,11 +252,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
p.save();
|
||||
p.translate(0, y);
|
||||
if (r.y() < y + item->height()) while (y < drawToY) {
|
||||
uint32 sel = 0;
|
||||
TextSelection sel;
|
||||
if (y >= selfromy && y < seltoy) {
|
||||
sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullSelection : 0;
|
||||
if (_dragSelecting && !item->serviceMsg() && item->id > 0) {
|
||||
sel = FullSelection;
|
||||
}
|
||||
} else if (hasSel) {
|
||||
SelectedItems::const_iterator i = _selected.constFind(item);
|
||||
auto i = _selected.constFind(item);
|
||||
if (i != selEnd) {
|
||||
sel = i.value();
|
||||
}
|
||||
|
@ -297,11 +299,13 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
while (y < drawToY) {
|
||||
int32 h = item->height();
|
||||
if (historyRect.y() < y + h && hdrawtop < y + h) {
|
||||
uint32 sel = 0;
|
||||
TextSelection sel;
|
||||
if (y >= selfromy && y < seltoy) {
|
||||
sel = (_dragSelecting && !item->serviceMsg() && item->id > 0) ? FullSelection : 0;
|
||||
if (_dragSelecting && !item->serviceMsg() && item->id > 0) {
|
||||
sel = FullSelection;
|
||||
}
|
||||
} else if (hasSel) {
|
||||
SelectedItems::const_iterator i = _selected.constFind(item);
|
||||
auto i = _selected.constFind(item);
|
||||
if (i != selEnd) {
|
||||
sel = i.value();
|
||||
}
|
||||
|
@ -588,19 +592,20 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
}
|
||||
}
|
||||
if (_dragAction == NoDrag && _dragItem) {
|
||||
bool afterDragSymbol, uponSymbol;
|
||||
uint16 symbol;
|
||||
HistoryTextState dragState;
|
||||
if (_trippleClickTimer.isActive() && (screenPos - _trippleClickPoint).manhattanLength() < QApplication::startDragDistance()) {
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSymbol, _dragStartPos.x(), _dragStartPos.y());
|
||||
if (uponSymbol) {
|
||||
uint32 selStatus = (symbol << 16) | symbol;
|
||||
HistoryStateRequest request;
|
||||
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
||||
dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
if (dragState.cursor == HistoryInTextCursorState) {
|
||||
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
}
|
||||
_selected.insert(_dragItem, selStatus);
|
||||
_dragSymbol = symbol;
|
||||
_dragSymbol = dragState.symbol;
|
||||
_dragAction = Selecting;
|
||||
_dragSelType = TextSelectParagraphs;
|
||||
dragActionUpdate(_dragPos);
|
||||
|
@ -608,12 +613,14 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
}
|
||||
}
|
||||
} else if (App::pressedItem()) {
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSymbol, _dragStartPos.x(), _dragStartPos.y());
|
||||
HistoryStateRequest request;
|
||||
request.flags = Text::StateRequest::Flag::LookupSymbol;
|
||||
dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
}
|
||||
if (_dragSelType != TextSelectParagraphs) {
|
||||
if (App::pressedItem()) {
|
||||
_dragSymbol = symbol;
|
||||
bool uponSelected = uponSymbol;
|
||||
_dragSymbol = dragState.symbol;
|
||||
bool uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||
if (uponSelected) {
|
||||
if (_selected.isEmpty() ||
|
||||
_selected.cbegin().value() == FullSelection ||
|
||||
|
@ -621,7 +628,7 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
) {
|
||||
uponSelected = false;
|
||||
} else {
|
||||
uint16 selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
|
||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
||||
if (_dragSymbol < selFrom || _dragSymbol >= selTo) {
|
||||
uponSelected = false;
|
||||
}
|
||||
|
@ -633,8 +640,8 @@ void HistoryInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton butt
|
|||
if (dynamic_cast<HistorySticker*>(App::pressedItem()->getMedia()) || _dragCursorState == HistoryInDateCursorState) {
|
||||
_dragAction = PrepareDrag; // start sticker drag or by-date drag
|
||||
} else {
|
||||
if (afterDragSymbol) ++_dragSymbol;
|
||||
uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
|
||||
if (dragState.afterSymbol) ++_dragSymbol;
|
||||
TextSelection selStatus = { _dragSymbol, _dragSymbol };
|
||||
if (selStatus != FullSelection && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
if (!_selected.isEmpty()) {
|
||||
repaintItem(_selected.cbegin().key());
|
||||
|
@ -675,12 +682,13 @@ void HistoryInner::onDragExec() {
|
|||
|
||||
bool uponSelected = false;
|
||||
if (_dragItem) {
|
||||
bool afterDragSymbol;
|
||||
uint16 symbol;
|
||||
if (!_selected.isEmpty() && _selected.cbegin().value() == FullSelection) {
|
||||
uponSelected = _selected.contains(_dragItem);
|
||||
} else {
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y());
|
||||
HistoryStateRequest request;
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
uponSelected = (dragState.cursor == HistoryInTextCursorState);
|
||||
if (uponSelected) {
|
||||
if (_selected.isEmpty() ||
|
||||
_selected.cbegin().value() == FullSelection ||
|
||||
|
@ -688,8 +696,8 @@ void HistoryInner::onDragExec() {
|
|||
) {
|
||||
uponSelected = false;
|
||||
} else {
|
||||
uint16 selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
|
||||
if (symbol < selFrom || symbol >= selTo) {
|
||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
||||
if (dragState.symbol < selFrom || dragState.symbol >= selTo) {
|
||||
uponSelected = false;
|
||||
}
|
||||
}
|
||||
|
@ -841,8 +849,8 @@ void HistoryInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton but
|
|||
applyDragSelection();
|
||||
_dragSelFrom = _dragSelTo = 0;
|
||||
} else if (!_selected.isEmpty() && !_dragWasInactive) {
|
||||
uint32 sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) {
|
||||
auto sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && sel.from == sel.to) {
|
||||
_selected.clear();
|
||||
if (App::wnd()) App::wnd()->setInnerFocus();
|
||||
}
|
||||
|
@ -867,15 +875,15 @@ void HistoryInner::mouseDoubleClickEvent(QMouseEvent *e) {
|
|||
|
||||
dragActionStart(e->globalPos(), e->button());
|
||||
if (((_dragAction == Selecting && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) || (_dragAction == NoDrag && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection))) && _dragSelType == TextSelectLetters && _dragItem) {
|
||||
bool afterDragSymbol, uponSelected;
|
||||
uint16 symbol;
|
||||
_dragItem->getSymbol(symbol, afterDragSymbol, uponSelected, _dragStartPos.x(), _dragStartPos.y());
|
||||
if (uponSelected) {
|
||||
_dragSymbol = symbol;
|
||||
HistoryStateRequest request;
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = _dragItem->getState(_dragStartPos.x(), _dragStartPos.y(), request);
|
||||
if (dragState.cursor == HistoryInTextCursorState) {
|
||||
_dragSymbol = dragState.symbol;
|
||||
_dragSelType = TextSelectWords;
|
||||
if (_dragAction == NoDrag) {
|
||||
_dragAction = Selecting;
|
||||
uint32 selStatus = (symbol << 16) | symbol;
|
||||
TextSelection selStatus = { dragState.symbol, dragState.symbol };
|
||||
if (!_selected.isEmpty()) {
|
||||
repaintItem(_selected.cbegin().key());
|
||||
_selected.clear();
|
||||
|
@ -915,13 +923,14 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
isUponSelected = -2;
|
||||
}
|
||||
} else {
|
||||
uint16 symbol, selFrom = (_selected.cbegin().value() >> 16) & 0xFFFF, selTo = _selected.cbegin().value() & 0xFFFF;
|
||||
uint16 selFrom = _selected.cbegin().value().from, selTo = _selected.cbegin().value().to;
|
||||
hasSelected = (selTo > selFrom) ? 1 : 0;
|
||||
if (App::mousedItem() && App::mousedItem() == App::hoveredItem()) {
|
||||
QPoint mousePos(mapMouseToItem(mapFromGlobal(_dragPos), App::mousedItem()));
|
||||
bool afterDragSymbol, uponSymbol;
|
||||
App::mousedItem()->getSymbol(symbol, afterDragSymbol, uponSymbol, mousePos.x(), mousePos.y());
|
||||
if (uponSymbol && symbol >= selFrom && symbol < selTo) {
|
||||
HistoryStateRequest request;
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
auto dragState = App::mousedItem()->getState(mousePos.x(), mousePos.y(), request);
|
||||
if (dragState.cursor == HistoryInTextCursorState && dragState.symbol >= selFrom && dragState.symbol < selTo) {
|
||||
isUponSelected = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1685,57 +1694,13 @@ void HistoryInner::onUpdateSelected() {
|
|||
dragActionCancel();
|
||||
}
|
||||
|
||||
ClickHandlerPtr lnk;
|
||||
HistoryTextState dragState;
|
||||
ClickHandlerHost *lnkhost = nullptr;
|
||||
HistoryCursorState cursorState = HistoryDefaultCursorState;
|
||||
bool selectingText = (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection);
|
||||
if (point.y() < _historyOffset) {
|
||||
if (_botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
|
||||
bool inText = false;
|
||||
_botAbout->info->text.getState(lnk, inText, point.x() - _botAbout->rect.left() - st::msgPadding.left(), point.y() - _botAbout->rect.top() - st::msgPadding.top() - st::botDescSkip - st::msgNameFont->height, _botAbout->width);
|
||||
dragState = _botAbout->info->text.getState(point.x() - _botAbout->rect.left() - st::msgPadding.left(), point.y() - _botAbout->rect.top() - st::msgPadding.top() - st::botDescSkip - st::msgNameFont->height, _botAbout->width);
|
||||
lnkhost = _botAbout.get();
|
||||
cursorState = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
}
|
||||
} else if (item) {
|
||||
item->getState(lnk, cursorState, m.x(), m.y());
|
||||
lnkhost = item;
|
||||
if (!lnk && m.x() >= st::msgMargin.left() && m.x() < st::msgMargin.left() + st::msgPhotoSize) {
|
||||
if (HistoryMessage *msg = item->toHistoryMessage()) {
|
||||
if (msg->hasFromPhoto()) {
|
||||
enumerateUserpics([&lnk, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
|
||||
// stop enumeration if the userpic is above our point
|
||||
if (userpicTop + st::msgPhotoSize <= point.y()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// stop enumeration if we've found a userpic under the cursor
|
||||
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
||||
lnk = message->from()->openLink();
|
||||
lnkhost = message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool lnkChanged = ClickHandler::setActive(lnk, lnkhost);
|
||||
if (lnkChanged || cursorState != _dragCursorState) {
|
||||
PopupTooltip::Hide();
|
||||
}
|
||||
if (lnk || cursorState == HistoryInDateCursorState || cursorState == HistoryInForwardedCursorState) {
|
||||
PopupTooltip::Show(1000, this);
|
||||
}
|
||||
|
||||
Qt::CursorShape cur = style::cur_default;
|
||||
if (_dragAction == NoDrag) {
|
||||
_dragCursorState = cursorState;
|
||||
if (lnk) {
|
||||
cur = style::cur_pointer;
|
||||
} else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
cur = style::cur_text;
|
||||
} else if (_dragCursorState == HistoryInDateCursorState) {
|
||||
// cur = style::cur_cross;
|
||||
}
|
||||
} else if (item) {
|
||||
if (item != _dragItem || (m - _dragStartPos).manhattanLength() >= QApplication::startDragDistance()) {
|
||||
|
@ -1746,19 +1711,68 @@ void HistoryInner::onUpdateSelected() {
|
|||
_dragAction = Selecting;
|
||||
}
|
||||
}
|
||||
|
||||
HistoryStateRequest request;
|
||||
if (_dragAction == Selecting) {
|
||||
bool canSelectMany = (_history != 0);
|
||||
if (item == _dragItem && item == App::hoveredItem() && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
||||
bool afterSymbol, uponSymbol;
|
||||
uint16 second;
|
||||
_dragItem->getSymbol(second, afterSymbol, uponSymbol, m.x(), m.y());
|
||||
if (afterSymbol && _dragSelType == TextSelectLetters) ++second;
|
||||
uint32 selState = _dragItem->adjustSelection(qMin(second, _dragSymbol), qMax(second, _dragSymbol), _dragSelType);
|
||||
request.flags |= Text::StateRequest::Flag::LookupSymbol;
|
||||
} else {
|
||||
selectingText = false;
|
||||
}
|
||||
dragState = item->getState(m.x(), m.y(), request);
|
||||
lnkhost = item;
|
||||
if (!dragState.link && m.x() >= st::msgMargin.left() && m.x() < st::msgMargin.left() + st::msgPhotoSize) {
|
||||
if (HistoryMessage *msg = item->toHistoryMessage()) {
|
||||
if (msg->hasFromPhoto()) {
|
||||
enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
|
||||
// stop enumeration if the userpic is above our point
|
||||
if (userpicTop + st::msgPhotoSize <= point.y()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// stop enumeration if we've found a userpic under the cursor
|
||||
if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
|
||||
dragState.link = message->from()->openLink();
|
||||
lnkhost = message;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
|
||||
if (lnkChanged || dragState.cursor != _dragCursorState) {
|
||||
PopupTooltip::Hide();
|
||||
}
|
||||
if (dragState.link || dragState.cursor == HistoryInDateCursorState || dragState.cursor == HistoryInForwardedCursorState) {
|
||||
PopupTooltip::Show(1000, this);
|
||||
}
|
||||
|
||||
Qt::CursorShape cur = style::cur_default;
|
||||
if (_dragAction == NoDrag) {
|
||||
_dragCursorState = dragState.cursor;
|
||||
if (dragState.link) {
|
||||
cur = style::cur_pointer;
|
||||
} else if (_dragCursorState == HistoryInTextCursorState && (_selected.isEmpty() || _selected.cbegin().value() != FullSelection)) {
|
||||
cur = style::cur_text;
|
||||
} else if (_dragCursorState == HistoryInDateCursorState) {
|
||||
// cur = style::cur_cross;
|
||||
}
|
||||
} else if (item) {
|
||||
if (_dragAction == Selecting) {
|
||||
bool canSelectMany = (_history != nullptr);
|
||||
if (selectingText) {
|
||||
uint16 second = dragState.symbol;
|
||||
if (dragState.afterSymbol && _dragSelType == TextSelectLetters) {
|
||||
++second;
|
||||
}
|
||||
auto selState = _dragItem->adjustSelection({ qMin(second, _dragSymbol), qMax(second, _dragSymbol) }, _dragSelType);
|
||||
if (_selected[_dragItem] != selState) {
|
||||
_selected[_dragItem] = selState;
|
||||
repaintItem(_dragItem);
|
||||
}
|
||||
if (!_wasSelectedText && (selState == FullSelection || (selState & 0xFFFF) != ((selState >> 16) & 0xFFFF))) {
|
||||
if (!_wasSelectedText && (selState == FullSelection || selState.from != selState.to)) {
|
||||
_wasSelectedText = true;
|
||||
setFocus();
|
||||
}
|
||||
|
@ -2009,7 +2023,7 @@ QString HistoryInner::tooltipText() const {
|
|||
} else if (_dragCursorState == HistoryInForwardedCursorState && _dragAction == NoDrag) {
|
||||
if (App::hoveredItem()) {
|
||||
if (HistoryMessageForwarded *fwd = App::hoveredItem()->Get<HistoryMessageForwarded>()) {
|
||||
return fwd->_text.original(0, 0xFFFF, Text::ExpandLinksNone);
|
||||
return fwd->_text.original(AllTextSelection, Text::ExpandLinksNone);
|
||||
}
|
||||
}
|
||||
} else if (ClickHandlerPtr lnk = ClickHandler::getActive()) {
|
||||
|
@ -2367,11 +2381,10 @@ void BotKeyboard::updateSelected() {
|
|||
QPoint p(mapFromGlobal(_lastMousePos));
|
||||
int x = rtl() ? st::botKbScroll.width : _st->margin;
|
||||
|
||||
ClickHandlerPtr lnk;
|
||||
_impl->getState(lnk, p.x() - x, p.y() - _st->margin);
|
||||
if (ClickHandler::setActive(lnk, this)) {
|
||||
auto link = _impl->getState(p.x() - x, p.y() - _st->margin);
|
||||
if (ClickHandler::setActive(link, this)) {
|
||||
PopupTooltip::Hide();
|
||||
setCursor(lnk ? style::cur_pointer : style::cur_default);
|
||||
setCursor(link ? style::cur_pointer : style::cur_default);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5927,6 +5940,7 @@ void HistoryWidget::inlineBotChanged() {
|
|||
_inlineBotCancel = std_::make_unique<IconedButton>(this, st::inlineBotCancel);
|
||||
connect(_inlineBotCancel.get(), SIGNAL(clicked()), this, SLOT(onInlineBotCancel()));
|
||||
_inlineBotCancel->setGeometry(_send.geometry());
|
||||
_attachEmoji.raise();
|
||||
updateFieldSubmitSettings();
|
||||
updateControlsVisibility();
|
||||
} else if (!isInlineBot && _inlineBotCancel) {
|
||||
|
|
|
@ -174,7 +174,7 @@ private:
|
|||
bool _firstLoading = false;
|
||||
|
||||
style::cursor _cursor = style::cur_default;
|
||||
typedef QMap<HistoryItem*, uint32> SelectedItems;
|
||||
using SelectedItems = QMap<HistoryItem*, TextSelection>;
|
||||
SelectedItems _selected;
|
||||
void applyDragSelection();
|
||||
void applyDragSelection(SelectedItems *toItems) const;
|
||||
|
|
|
@ -125,7 +125,7 @@ void DeleteSavedGifClickHandler::onClickImpl() const {
|
|||
if (App::main()) emit App::main()->savedGifsUpdated();
|
||||
}
|
||||
|
||||
void Gif::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
DocumentData *document = getShownDocument();
|
||||
document->automaticLoad(nullptr);
|
||||
|
||||
|
@ -381,7 +381,7 @@ void Sticker::preload() const {
|
|||
}
|
||||
}
|
||||
|
||||
void Sticker::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
bool loaded = getShownDocument()->loaded();
|
||||
|
||||
float64 over = _a_over.isNull() ? (_active ? 1 : 0) : _a_over.current();
|
||||
|
@ -473,7 +473,7 @@ void Photo::initDimensions() {
|
|||
_minh = st::inlineMediaHeight + st::inlineResultsSkip;
|
||||
}
|
||||
|
||||
void Photo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Photo::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 height = st::inlineMediaHeight;
|
||||
QSize frame = countFrameSize();
|
||||
|
||||
|
@ -591,7 +591,7 @@ void Video::initDimensions() {
|
|||
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||
}
|
||||
|
||||
void Video::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Video::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||
|
||||
bool withThumb = !content_thumb()->isNull();
|
||||
|
@ -694,7 +694,7 @@ void File::initDimensions() {
|
|||
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||
}
|
||||
|
||||
void File::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void File::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 left = st::msgFileSize + st::inlineThumbSkip;
|
||||
|
||||
DocumentData *document = getShownDocument();
|
||||
|
@ -942,7 +942,7 @@ int32 Contact::resizeGetHeight(int32 width) {
|
|||
return _height;
|
||||
}
|
||||
|
||||
void Contact::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Contact::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 left = st::emojiPanHeaderLeft - st::inlineResultsLeft;
|
||||
|
||||
left = st::msgFileSize + st::inlineThumbSkip;
|
||||
|
@ -1051,7 +1051,7 @@ int32 Article::resizeGetHeight(int32 width) {
|
|||
return _height;
|
||||
}
|
||||
|
||||
void Article::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Article::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
int32 left = st::emojiPanHeaderLeft - st::inlineResultsLeft;
|
||||
if (_withThumb) {
|
||||
left = st::inlineThumbSize + st::inlineThumbSkip;
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
|
@ -135,7 +135,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
@ -165,7 +165,7 @@ public:
|
|||
}
|
||||
void preload() const override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
|
@ -190,7 +190,7 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
@ -238,7 +238,7 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
// ClickHandlerHost interface
|
||||
|
@ -302,7 +302,7 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
@ -321,7 +321,7 @@ public:
|
|||
void initDimensions() override;
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
//ItemBase(PhotoData *photo) : _photo(photo) {
|
||||
//}
|
||||
|
||||
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const = 0;
|
||||
virtual void paint(Painter &p, const QRect &clip, const PaintContext *context) const = 0;
|
||||
|
||||
virtual void setPosition(int32 position);
|
||||
int32 position() const;
|
||||
|
|
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
static const uint32 FullSelection = 0xFFFFFFFF;
|
||||
static constexpr TextSelection FullSelection = { 0xFFFF, 0xFFFF };
|
||||
|
||||
extern TextParseOptions _textNameOptions, _textDlgOptions;
|
||||
extern TextParseOptions _historyTextOptions, _historyBotOptions, _historyTextNoMonoOptions, _historyBotNoMonoOptions;
|
||||
|
|
|
@ -1781,13 +1781,14 @@ bool MediaView::updateOverState(OverState newState) {
|
|||
void MediaView::updateOver(QPoint pos) {
|
||||
ClickHandlerPtr lnk;
|
||||
ClickHandlerHost *lnkhost = nullptr;
|
||||
bool inText;
|
||||
|
||||
if (_saveMsgStarted && _saveMsg.contains(pos)) {
|
||||
_saveMsgText.getState(lnk, inText, pos.x() - _saveMsg.x() - st::medviewSaveMsgPadding.left(), pos.y() - _saveMsg.y() - st::medviewSaveMsgPadding.top(), _saveMsg.width() - st::medviewSaveMsgPadding.left() - st::medviewSaveMsgPadding.right());
|
||||
auto textState = _saveMsgText.getState(pos.x() - _saveMsg.x() - st::medviewSaveMsgPadding.left(), pos.y() - _saveMsg.y() - st::medviewSaveMsgPadding.top(), _saveMsg.width() - st::medviewSaveMsgPadding.left() - st::medviewSaveMsgPadding.right());
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
} else if (_captionRect.contains(pos)) {
|
||||
_caption.getState(lnk, inText, pos.x() - _captionRect.x(), pos.y() - _captionRect.y(), _captionRect.width());
|
||||
auto textState = _caption.getState(pos.x() - _captionRect.x(), pos.y() - _captionRect.y(), _captionRect.width());
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ void Date::initDimensions() {
|
|||
_minh = st::linksDateMargin.top() + st::normalFont->height + st::linksDateMargin.bottom() + st::linksBorder;
|
||||
}
|
||||
|
||||
void Date::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
||||
if (clip.intersects(QRect(0, st::linksDateMargin.top(), _width, st::normalFont->height))) {
|
||||
p.setPen(st::linksDateColor);
|
||||
p.setFont(st::semiboldFont);
|
||||
|
@ -159,7 +159,7 @@ int32 Photo::resizeGetHeight(int32 width) {
|
|||
return _height;
|
||||
}
|
||||
|
||||
void Photo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
||||
bool good = _data->loaded();
|
||||
if (!good) {
|
||||
_data->medium->automaticLoad(_parent);
|
||||
|
@ -230,7 +230,7 @@ int32 Video::resizeGetHeight(int32 width) {
|
|||
return _height;
|
||||
}
|
||||
|
||||
void Video::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
||||
bool selected = (selection == FullSelection), thumbLoaded = _data->thumb->loaded();
|
||||
|
||||
_data->automaticLoad(_parent);
|
||||
|
@ -397,7 +397,7 @@ void Voice::initDimensions() {
|
|||
_minh = st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom() + st::lineWidth;
|
||||
}
|
||||
|
||||
void Voice::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
||||
bool selected = (selection == FullSelection);
|
||||
|
||||
_data->automaticLoad(_parent);
|
||||
|
@ -515,9 +515,9 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
|
|||
}
|
||||
if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) {
|
||||
if (_statusSize == FileStatusSizeLoaded || _statusSize == FileStatusSizeReady) {
|
||||
bool inText = false;
|
||||
_details.getStateLeft(link, inText, x - nameleft, y - statustop, _width, _width);
|
||||
cursor = inText ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
auto textState = _details.getStateLeft(x - nameleft, y - statustop, _width, _width);
|
||||
link = textState.link;
|
||||
cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
|
||||
}
|
||||
}
|
||||
if (hasPoint(x, y) && !link && !_data->loading()) {
|
||||
|
@ -615,7 +615,7 @@ void Document::initDimensions() {
|
|||
}
|
||||
}
|
||||
|
||||
void Document::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Document::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
||||
bool selected = (selection == FullSelection);
|
||||
|
||||
_data->automaticLoad(_parent);
|
||||
|
@ -1027,7 +1027,7 @@ int32 Link::resizeGetHeight(int32 width) {
|
|||
return _height;
|
||||
}
|
||||
|
||||
void Link::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const {
|
||||
void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
|
||||
int32 left = st::dlgPhotoSize + st::dlgPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
|
||||
if (clip.intersects(rtlrect(0, top, st::dlgPhotoSize, st::dlgPhotoSize, _width))) {
|
||||
if (_page && _page->photo) {
|
||||
|
|
|
@ -38,7 +38,7 @@ class ItemBase;
|
|||
class AbstractItem : public LayoutItemBase {
|
||||
public:
|
||||
|
||||
virtual void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const = 0;
|
||||
virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const = 0;
|
||||
|
||||
virtual ItemBase *toMediaItem() {
|
||||
return nullptr;
|
||||
|
@ -164,7 +164,7 @@ public:
|
|||
Date(const QDate &date, bool month);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
|
||||
private:
|
||||
QDate _date;
|
||||
|
@ -178,7 +178,7 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
@ -196,7 +196,7 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
protected:
|
||||
|
@ -229,7 +229,7 @@ public:
|
|||
Voice(DocumentData *voice, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
protected:
|
||||
|
@ -263,7 +263,7 @@ public:
|
|||
Document(DocumentData *document, HistoryItem *parent);
|
||||
|
||||
void initDimensions() override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
virtual DocumentData *getDocument() const override {
|
||||
|
@ -308,7 +308,7 @@ public:
|
|||
|
||||
void initDimensions() override;
|
||||
int32 resizeGetHeight(int32 width) override;
|
||||
void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override;
|
||||
void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
|
||||
void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -566,8 +566,8 @@ void OverviewInner::dragActionFinish(const QPoint &screenPos, Qt::MouseButton bu
|
|||
if (_dragSelFrom && _dragSelTo) {
|
||||
applyDragSelection();
|
||||
} else if (!_selected.isEmpty() && !_dragWasInactive) {
|
||||
uint32 sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && (sel & 0xFFFF) == ((sel >> 16) & 0xFFFF)) {
|
||||
auto sel = _selected.cbegin().value();
|
||||
if (sel != FullSelection && sel.from == sel.to) {
|
||||
_selected.clear();
|
||||
App::main()->activate();
|
||||
}
|
||||
|
@ -782,7 +782,7 @@ bool OverviewInner::preloadLocal() {
|
|||
return true;
|
||||
}
|
||||
|
||||
uint32 OverviewInner::itemSelectedValue(int32 index) const {
|
||||
TextSelection OverviewInner::itemSelectedValue(int32 index) const {
|
||||
int32 selfrom = -1, selto = -1;
|
||||
if (_dragSelFromIndex >= 0 && _dragSelToIndex >= 0) {
|
||||
selfrom = _dragSelToIndex;
|
||||
|
@ -790,7 +790,7 @@ uint32 OverviewInner::itemSelectedValue(int32 index) const {
|
|||
}
|
||||
if (_items.at(index)->toMediaItem()) { // draw item
|
||||
if (index >= _dragSelToIndex && index <= _dragSelFromIndex && _dragSelToIndex >= 0) {
|
||||
return (_dragSelecting && _items.at(index)->msgId() > 0) ? FullSelection : 0;
|
||||
return (_dragSelecting && _items.at(index)->msgId() > 0) ? FullSelection : TextSelection{ 0, 0 };
|
||||
} else if (!_selected.isEmpty()) {
|
||||
SelectedItems::const_iterator j = _selected.constFind(complexMsgId(_items.at(index)->getItem()));
|
||||
if (j != _selected.cend()) {
|
||||
|
@ -798,7 +798,7 @@ uint32 OverviewInner::itemSelectedValue(int32 index) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
void OverviewInner::paintEvent(QPaintEvent *e) {
|
||||
|
@ -1010,7 +1010,7 @@ void OverviewInner::onUpdateSelected() {
|
|||
if (_mousedItem == _dragItem && lnk && !_selected.isEmpty() && _selected.cbegin().value() != FullSelection) {
|
||||
bool afterSymbol = false, uponSymbol = false;
|
||||
uint16 second = 0;
|
||||
_selected[_dragItem] = 0;
|
||||
_selected[_dragItem] = { 0, 0 };
|
||||
updateDragSelection(0, -1, 0, -1, false);
|
||||
} else if (canSelectMany) {
|
||||
bool selectingDown = (_reversed ? (_mousedItemIndex < _dragItemIndex) : (_mousedItemIndex > _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && ((_type == OverviewPhotos || _type == OverviewVideos) ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y())));
|
||||
|
@ -1729,7 +1729,7 @@ void OverviewInner::changingMsgId(HistoryItem *row, MsgId newId) {
|
|||
if (_selectedMsgId == oldId) _selectedMsgId = newId;
|
||||
for (SelectedItems::iterator i = _selected.begin(), e = _selected.end(); i != e; ++i) {
|
||||
if (i.key() == oldId) {
|
||||
uint32 sel = i.value();
|
||||
auto sel = i.value();
|
||||
_selected.erase(i);
|
||||
_selected.insert(newId, sel);
|
||||
break;
|
||||
|
|
|
@ -158,7 +158,7 @@ private:
|
|||
ChannelId _channel;
|
||||
|
||||
bool _selMode;
|
||||
uint32 itemSelectedValue(int32 index) const;
|
||||
TextSelection itemSelectedValue(int32 index) const;
|
||||
|
||||
int32 _rowsLeft, _rowWidth;
|
||||
|
||||
|
@ -209,7 +209,7 @@ private:
|
|||
// selection support, like in HistoryWidget
|
||||
Qt::CursorShape _cursor;
|
||||
HistoryCursorState _cursorState;
|
||||
typedef QMap<MsgId, uint32> SelectedItems;
|
||||
using SelectedItems = QMap<MsgId, TextSelection>;
|
||||
SelectedItems _selected;
|
||||
enum DragAction {
|
||||
NoDrag = 0x00,
|
||||
|
|
|
@ -1120,9 +1120,9 @@ void ProfileInner::updateSelected() {
|
|||
|
||||
ClickHandlerPtr lnk;
|
||||
ClickHandlerHost *lnkhost = nullptr;
|
||||
bool inText = false;
|
||||
if (!_about.isEmpty() && lp.y() >= _aboutTop && lp.y() < _aboutTop + _aboutHeight && lp.x() >= _left && lp.x() < _left + _width) {
|
||||
_about.getState(lnk, inText, lp.x() - _left, lp.y() - _aboutTop, _width);
|
||||
auto textState = _about.getState(lp.x() - _left, lp.y() - _aboutTop, _width);
|
||||
lnk = textState.link;
|
||||
lnkhost = this;
|
||||
}
|
||||
ClickHandler::setActive(lnk, lnkhost);
|
||||
|
|
|
@ -110,10 +110,12 @@ void FlatLabel::updateHover() {
|
|||
QPoint m(mapFromGlobal(_lastMousePos));
|
||||
|
||||
textstyleSet(&_tst);
|
||||
ClickHandlerPtr handler = _text.link(m.x(), m.y(), width(), _st.align);
|
||||
Text::StateRequest request;
|
||||
request.align = _st.align;
|
||||
auto state = _text.getState(m.x(), m.y(), width(), request);
|
||||
textstyleRestore();
|
||||
|
||||
ClickHandler::setActive(handler, this);
|
||||
ClickHandler::setActive(state.link, this);
|
||||
}
|
||||
|
||||
void FlatLabel::setOpacity(float64 o) {
|
||||
|
|
|
@ -923,7 +923,7 @@ public:
|
|||
return _blockEnd(t, i, e) - (*i)->from();
|
||||
}
|
||||
|
||||
TextPainter(QPainter *p, const Text *t) : _p(p), _t(t), _elideLast(false), _breakEverywhere(false), _elideRemoveFromEnd(0), _str(0), _elideSavedBlock(0), _lnkResult(0), _inTextFlag(0), _getSymbol(0), _getSymbolAfter(0), _getSymbolUpon(0) {
|
||||
TextPainter(QPainter *p, const Text *t) : _p(p), _t(t) {
|
||||
}
|
||||
|
||||
void initNextParagraph(Text::TextBlocks::const_iterator i) {
|
||||
|
@ -987,7 +987,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void draw(int32 left, int32 top, int32 w, style::align align, int32 yFrom, int32 yTo, uint16 selectedFrom = 0, uint16 selectedTo = 0) {
|
||||
void draw(int32 left, int32 top, int32 w, style::align align, int32 yFrom, int32 yTo, TextSelection selection = { 0, 0 }) {
|
||||
if (_t->isEmpty()) return;
|
||||
|
||||
_blocksSize = _t->_blocks.size();
|
||||
|
@ -1005,8 +1005,7 @@ public:
|
|||
if (_elideLast) {
|
||||
_yToElide = _yTo;
|
||||
}
|
||||
_selectedFrom = selectedFrom;
|
||||
_selectedTo = selectedTo;
|
||||
_selection = selection;
|
||||
_wLeft = _w = w;
|
||||
_str = _t->_text.unicode();
|
||||
|
||||
|
@ -1173,14 +1172,13 @@ public:
|
|||
if (_lineStart < _t->_text.size()) {
|
||||
if (!drawLine(_t->_text.size(), e, e)) return;
|
||||
}
|
||||
if (_getSymbol) {
|
||||
*_getSymbol = _t->_text.size();
|
||||
*_getSymbolAfter = false;
|
||||
*_getSymbolUpon = false;
|
||||
if (!_p && _lookupSymbol) {
|
||||
_lookupResult.symbol = _t->_text.size();
|
||||
_lookupResult.afterSymbol = false;
|
||||
}
|
||||
}
|
||||
|
||||
void drawElided(int32 left, int32 top, int32 w, style::align align, int32 lines, int32 yFrom, int32 yTo, int32 removeFromEnd, bool breakEverywhere) {
|
||||
void drawElided(int32 left, int32 top, int32 w, style::align align, int32 lines, int32 yFrom, int32 yTo, int32 removeFromEnd, bool breakEverywhere, TextSelection selection) {
|
||||
if (lines <= 0 || _t->isNull()) return;
|
||||
|
||||
if (yTo < 0 || (lines - 1) * _t->_font->height < yTo) {
|
||||
|
@ -1189,48 +1187,45 @@ public:
|
|||
_elideRemoveFromEnd = removeFromEnd;
|
||||
}
|
||||
_breakEverywhere = breakEverywhere;
|
||||
draw(left, top, w, align, yFrom, yTo);
|
||||
draw(left, top, w, align, yFrom, yTo, selection);
|
||||
}
|
||||
|
||||
const ClickHandlerPtr &link(int32 x, int32 y, int32 w, style::align align) {
|
||||
static StaticNeverFreedPointer<ClickHandlerPtr> zero(new ClickHandlerPtr());
|
||||
|
||||
_lnkX = x;
|
||||
_lnkY = y;
|
||||
_lnkResult = zero.data();
|
||||
if (!_t->isNull() && _lnkX >= 0 && _lnkX < w && _lnkY >= 0) {
|
||||
draw(0, 0, w, align, _lnkY, _lnkY + 1);
|
||||
}
|
||||
return *_lnkResult;
|
||||
}
|
||||
|
||||
void getState(ClickHandlerPtr &lnk, bool &inText, int32 x, int32 y, int32 w, style::align align, bool breakEverywhere) {
|
||||
lnk.clear();
|
||||
inText = false;
|
||||
|
||||
if (!_t->isNull() && x >= 0 && x < w && y >= 0) {
|
||||
_lnkX = x;
|
||||
_lnkY = y;
|
||||
_lnkResult = &lnk;
|
||||
_inTextFlag = &inText;
|
||||
_breakEverywhere = breakEverywhere;
|
||||
draw(0, 0, w, align, _lnkY, _lnkY + 1);
|
||||
lnk = *_lnkResult;
|
||||
}
|
||||
}
|
||||
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 w, style::align align) {
|
||||
symbol = 0;
|
||||
after = false;
|
||||
upon = false;
|
||||
Text::StateResult getState(int x, int y, int w, Text::StateRequest request) {
|
||||
if (!_t->isNull() && y >= 0) {
|
||||
_lnkX = x;
|
||||
_lnkY = y;
|
||||
_getSymbol = &symbol;
|
||||
_getSymbolAfter = &after;
|
||||
_getSymbolUpon = &upon;
|
||||
draw(0, 0, w, align, _lnkY, _lnkY + 1);
|
||||
_lookupRequest = request;
|
||||
_lookupX = x;
|
||||
_lookupY = y;
|
||||
|
||||
_breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere);
|
||||
_lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol);
|
||||
_lookupLink = (_lookupRequest.flags & Text::StateRequest::Flag::LookupLink);
|
||||
if (_lookupSymbol || (_lookupX >= 0 && _lookupX < w)) {
|
||||
draw(0, 0, w, _lookupRequest.align, _lookupY, _lookupY + 1);
|
||||
}
|
||||
}
|
||||
return _lookupResult;
|
||||
}
|
||||
|
||||
Text::StateResult getStateElided(int x, int y, int w, Text::StateRequestElided request) {
|
||||
if (!_t->isNull() && y >= 0 && request.lines > 0) {
|
||||
_lookupRequest = request;
|
||||
_lookupX = x;
|
||||
_lookupY = y;
|
||||
|
||||
_breakEverywhere = (_lookupRequest.flags & Text::StateRequest::Flag::BreakEverywhere);
|
||||
_lookupSymbol = (_lookupRequest.flags & Text::StateRequest::Flag::LookupSymbol);
|
||||
_lookupLink = (_lookupRequest.flags & Text::StateRequest::Flag::LookupLink);
|
||||
if (_lookupSymbol || (_lookupX >= 0 && _lookupX < w)) {
|
||||
int yTo = _lookupY + 1;
|
||||
if (yTo < 0 || (request.lines - 1) * _t->_font->height < yTo) {
|
||||
yTo = request.lines * _t->_font->height;
|
||||
_elideLast = true;
|
||||
_elideRemoveFromEnd = request.removeFromEnd;
|
||||
}
|
||||
draw(0, 0, w, _lookupRequest.align, _lookupY, _lookupY + 1);
|
||||
}
|
||||
}
|
||||
return _lookupResult;
|
||||
}
|
||||
|
||||
const QPen &blockPen(ITextBlock *block) {
|
||||
|
@ -1288,34 +1283,44 @@ public:
|
|||
x += _wLeft;
|
||||
}
|
||||
|
||||
if (_getSymbol) {
|
||||
if (_lnkX < x) {
|
||||
if (_parDirection == Qt::RightToLeft) {
|
||||
*_getSymbol = (_lineEnd > _lineStart) ? (_lineEnd - 1) : _lineStart;
|
||||
*_getSymbolAfter = (_lineEnd > _lineStart) ? true : false;
|
||||
*_getSymbolUpon = ((_lnkX >= _x) && (_lineEnd < _t->_text.size()) && (!_endBlock || _endBlock->type() != TextBlockTSkip)) ? true : false;
|
||||
} else {
|
||||
*_getSymbol = _lineStart;
|
||||
*_getSymbolAfter = false;
|
||||
*_getSymbolUpon = ((_lnkX >= _x) && (_lineStart > 0)) ? true : false;
|
||||
if (!_p) {
|
||||
if (_lookupX < x) {
|
||||
if (_lookupSymbol) {
|
||||
if (_parDirection == Qt::RightToLeft) {
|
||||
_lookupResult.symbol = (_lineEnd > _lineStart) ? (_lineEnd - 1) : _lineStart;
|
||||
_lookupResult.afterSymbol = (_lineEnd > _lineStart) ? true : false;
|
||||
// _lookupResult.uponSymbol = ((_lookupX >= _x) && (_lineEnd < _t->_text.size()) && (!_endBlock || _endBlock->type() != TextBlockTSkip)) ? true : false;
|
||||
} else {
|
||||
_lookupResult.symbol = _lineStart;
|
||||
_lookupResult.afterSymbol = false;
|
||||
// _lookupResult.uponSymbol = ((_lookupX >= _x) && (_lineStart > 0)) ? true : false;
|
||||
}
|
||||
}
|
||||
if (_lookupLink) {
|
||||
_lookupResult.link.clear();
|
||||
}
|
||||
_lookupResult.uponSymbol = false;
|
||||
return false;
|
||||
} else if (_lnkX >= x + (_w - _wLeft)) {
|
||||
} else if (_lookupX >= x + (_w - _wLeft)) {
|
||||
if (_parDirection == Qt::RightToLeft) {
|
||||
*_getSymbol = _lineStart;
|
||||
*_getSymbolAfter = false;
|
||||
*_getSymbolUpon = ((_lnkX < _x + _w) && (_lineStart > 0)) ? true : false;
|
||||
_lookupResult.symbol = _lineStart;
|
||||
_lookupResult.afterSymbol = false;
|
||||
// _lookupResult.uponSymbol = ((_lookupX < _x + _w) && (_lineStart > 0)) ? true : false;
|
||||
} else {
|
||||
*_getSymbol = (_lineEnd > _lineStart) ? (_lineEnd - 1) : _lineStart;
|
||||
*_getSymbolAfter = (_lineEnd > _lineStart) ? true : false;
|
||||
*_getSymbolUpon = ((_lnkX < _x + _w) && (_lineEnd < _t->_text.size()) && (!_endBlock || _endBlock->type() != TextBlockTSkip)) ? true : false;
|
||||
_lookupResult.symbol = (_lineEnd > _lineStart) ? (_lineEnd - 1) : _lineStart;
|
||||
_lookupResult.afterSymbol = (_lineEnd > _lineStart) ? true : false;
|
||||
// _lookupResult.uponSymbol = ((_lookupX < _x + _w) && (_lineEnd < _t->_text.size()) && (!_endBlock || _endBlock->type() != TextBlockTSkip)) ? true : false;
|
||||
}
|
||||
if (_lookupLink) {
|
||||
_lookupResult.link.clear();
|
||||
}
|
||||
_lookupResult.uponSymbol = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool selectFromStart = (_selectedTo > _lineStart) && (_lineStart > 0) && (_selectedFrom <= _lineStart);
|
||||
bool selectTillEnd = (_selectedTo >= _lineEnd) && (_lineEnd < _t->_text.size()) && (_selectedFrom < _lineEnd) && (!_endBlock || _endBlock->type() != TextBlockTSkip);
|
||||
bool selectFromStart = (_selection.to > _lineStart) && (_lineStart > 0) && (_selection.from <= _lineStart);
|
||||
bool selectTillEnd = (_selection.to >= _lineEnd) && (_lineEnd < _t->_text.size()) && (_selection.from < _lineEnd) && (!_endBlock || _endBlock->type() != TextBlockTSkip);
|
||||
|
||||
if ((selectFromStart && _parDirection == Qt::LeftToRight) || (selectTillEnd && _parDirection == Qt::RightToLeft)) {
|
||||
if (x > _x) {
|
||||
|
@ -1409,52 +1414,48 @@ public:
|
|||
}
|
||||
if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
|
||||
TextBlockType _type = currentBlock->type();
|
||||
if (_lnkResult && _lnkX >= x && _lnkX < x + si.width) {
|
||||
if (currentBlock->lnkIndex() && _lnkY >= _y + _yDelta && _lnkY < _y + _yDelta + _fontHeight) {
|
||||
_lnkResult = &_t->_links.at(currentBlock->lnkIndex() - 1);
|
||||
}
|
||||
if (_inTextFlag && _type != TextBlockTSkip) {
|
||||
*_inTextFlag = true;
|
||||
}
|
||||
return false;
|
||||
} else if (_getSymbol && _lnkX >= x && _lnkX < x + si.width) {
|
||||
if (_type == TextBlockTSkip) {
|
||||
if (_parDirection == Qt::RightToLeft) {
|
||||
*_getSymbol = _lineStart;
|
||||
*_getSymbolAfter = false;
|
||||
*_getSymbolUpon = false;
|
||||
} else {
|
||||
*_getSymbol = (trimmedLineEnd > _lineStart) ? (trimmedLineEnd - 1) : _lineStart;
|
||||
*_getSymbolAfter = (trimmedLineEnd > _lineStart) ? true : false;
|
||||
*_getSymbolUpon = false;
|
||||
if (!_p && _lookupX >= x && _lookupX < x + si.width) { // _lookupRequest
|
||||
if (_lookupLink) {
|
||||
if (currentBlock->lnkIndex() && _lookupY >= _y + _yDelta && _lookupY < _y + _yDelta + _fontHeight) {
|
||||
_lookupResult.link = _t->_links.at(currentBlock->lnkIndex() - 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const QChar *chFrom = _str + currentBlock->from(), *chTo = chFrom + ((nextBlock ? nextBlock->from() : _t->_text.size()) - currentBlock->from());
|
||||
if (chTo > chFrom && (chTo - 1)->unicode() == QChar::Space) {
|
||||
if (rtl) {
|
||||
if (_lnkX < x + (si.width - currentBlock->f_width())) {
|
||||
*_getSymbol = (chTo - 1 - _str); // up to ending space, included, rtl
|
||||
*_getSymbolAfter = (_lnkX < x + (si.width - currentBlock->f_width()) / 2) ? true : false;
|
||||
*_getSymbolUpon = true;
|
||||
return false;
|
||||
if (_type != TextBlockTSkip) {
|
||||
_lookupResult.uponSymbol = true;
|
||||
}
|
||||
if (_lookupSymbol) {
|
||||
if (_type == TextBlockTSkip) {
|
||||
if (_parDirection == Qt::RightToLeft) {
|
||||
_lookupResult.symbol = _lineStart;
|
||||
_lookupResult.afterSymbol = false;
|
||||
} else {
|
||||
_lookupResult.symbol = (trimmedLineEnd > _lineStart) ? (trimmedLineEnd - 1) : _lineStart;
|
||||
_lookupResult.afterSymbol = (trimmedLineEnd > _lineStart) ? true : false;
|
||||
}
|
||||
} else if (_lnkX >= x + currentBlock->f_width()) {
|
||||
*_getSymbol = (chTo - 1 - _str); // up to ending space, inclided, ltr
|
||||
*_getSymbolAfter = (_lnkX >= x + currentBlock->f_width() + (currentBlock->f_rpadding() / 2)) ? true : false;
|
||||
*_getSymbolUpon = true;
|
||||
return false;
|
||||
}
|
||||
--chTo;
|
||||
}
|
||||
if (_lnkX < x + (rtl ? (si.width - currentBlock->f_width()) : 0) + (currentBlock->f_width() / 2)) {
|
||||
*_getSymbol = ((rtl && chTo > chFrom) ? (chTo - 1) : chFrom) - _str;
|
||||
*_getSymbolAfter = (rtl && chTo > chFrom) ? true : false;
|
||||
*_getSymbolUpon = true;
|
||||
} else {
|
||||
*_getSymbol = ((rtl || chTo <= chFrom) ? chFrom : (chTo - 1)) - _str;
|
||||
*_getSymbolAfter = (rtl || chTo <= chFrom) ? false : true;
|
||||
*_getSymbolUpon = true;
|
||||
const QChar *chFrom = _str + currentBlock->from(), *chTo = chFrom + ((nextBlock ? nextBlock->from() : _t->_text.size()) - currentBlock->from());
|
||||
if (chTo > chFrom && (chTo - 1)->unicode() == QChar::Space) {
|
||||
if (rtl) {
|
||||
if (_lookupX < x + (si.width - currentBlock->f_width())) {
|
||||
_lookupResult.symbol = (chTo - 1 - _str); // up to ending space, included, rtl
|
||||
_lookupResult.afterSymbol = (_lookupX < x + (si.width - currentBlock->f_width()) / 2) ? true : false;
|
||||
return false;
|
||||
}
|
||||
} else if (_lookupX >= x + currentBlock->f_width()) {
|
||||
_lookupResult.symbol = (chTo - 1 - _str); // up to ending space, inclided, ltr
|
||||
_lookupResult.afterSymbol = (_lookupX >= x + currentBlock->f_width() + (currentBlock->f_rpadding() / 2)) ? true : false;
|
||||
return false;
|
||||
}
|
||||
--chTo;
|
||||
}
|
||||
if (_lookupX < x + (rtl ? (si.width - currentBlock->f_width()) : 0) + (currentBlock->f_width() / 2)) {
|
||||
_lookupResult.symbol = ((rtl && chTo > chFrom) ? (chTo - 1) : chFrom) - _str;
|
||||
_lookupResult.afterSymbol = (rtl && chTo > chFrom) ? true : false;
|
||||
} else {
|
||||
_lookupResult.symbol = ((rtl || chTo <= chFrom) ? chFrom : (chTo - 1)) - _str;
|
||||
_lookupResult.afterSymbol = (rtl || chTo <= chFrom) ? false : true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (_p && _type == TextBlockTEmoji) {
|
||||
|
@ -1462,15 +1463,15 @@ public:
|
|||
if (rtl) {
|
||||
glyphX += (si.width - currentBlock->f_width());
|
||||
}
|
||||
if (_localFrom + si.position < _selectedTo) {
|
||||
if (_localFrom + si.position < _selection.to) {
|
||||
const QChar *chFrom = _str + currentBlock->from(), *chTo = chFrom + ((nextBlock ? nextBlock->from() : _t->_text.size()) - currentBlock->from());
|
||||
if (_localFrom + si.position >= _selectedFrom) { // could be without space
|
||||
if (chTo == chFrom || (chTo - 1)->unicode() != QChar::Space || _selectedTo >= (chTo - _str)) {
|
||||
if (_localFrom + si.position >= _selection.from) { // could be without space
|
||||
if (chTo == chFrom || (chTo - 1)->unicode() != QChar::Space || _selection.to >= (chTo - _str)) {
|
||||
_p->fillRect(QRectF(x.toReal(), _y + _yDelta, si.width.toReal(), _fontHeight), _textStyle->selectBg->b);
|
||||
} else { // or with space
|
||||
_p->fillRect(QRectF(glyphX.toReal(), _y + _yDelta, currentBlock->f_width().toReal(), _fontHeight), _textStyle->selectBg->b);
|
||||
}
|
||||
} else if (chTo > chFrom && (chTo - 1)->unicode() == QChar::Space && (chTo - 1 - _str) >= _selectedFrom) {
|
||||
} else if (chTo > chFrom && (chTo - 1)->unicode() == QChar::Space && (chTo - 1 - _str) >= _selection.from) {
|
||||
if (rtl) { // rtl space only
|
||||
_p->fillRect(QRectF(x.toReal(), _y + _yDelta, (glyphX - x).toReal(), _fontHeight), _textStyle->selectBg->b);
|
||||
} else { // ltr space only
|
||||
|
@ -1504,54 +1505,52 @@ public:
|
|||
for (int g = glyphsStart; g < glyphsEnd; ++g)
|
||||
itemWidth += glyphs.effectiveAdvance(g);
|
||||
|
||||
if (_lnkResult && _lnkX >= x && _lnkX < x + itemWidth) {
|
||||
if (currentBlock->lnkIndex() && _lnkY >= _y + _yDelta && _lnkY < _y + _yDelta + _fontHeight) {
|
||||
_lnkResult = &_t->_links.at(currentBlock->lnkIndex() - 1);
|
||||
}
|
||||
if (_inTextFlag) {
|
||||
*_inTextFlag = true;
|
||||
}
|
||||
return false;
|
||||
} else if (_getSymbol && _lnkX >= x && _lnkX < x + itemWidth) {
|
||||
QFixed tmpx = rtl ? (x + itemWidth) : x;
|
||||
for (int ch = 0, g, itemL = itemEnd - itemStart; ch < itemL;) {
|
||||
g = logClusters[itemStart - si.position + ch];
|
||||
QFixed gwidth = glyphs.effectiveAdvance(g);
|
||||
// ch2 - glyph end, ch - glyph start, (ch2 - ch) - how much chars it takes
|
||||
int ch2 = ch + 1;
|
||||
while ((ch2 < itemL) && (g == logClusters[itemStart - si.position + ch2])) {
|
||||
++ch2;
|
||||
if (!_p && _lookupX >= x && _lookupX < x + itemWidth) { // _lookupRequest
|
||||
if (_lookupLink) {
|
||||
if (currentBlock->lnkIndex() && _lookupY >= _y + _yDelta && _lookupY < _y + _yDelta + _fontHeight) {
|
||||
_lookupResult.link = _t->_links.at(currentBlock->lnkIndex() - 1);
|
||||
}
|
||||
for (int charsCount = (ch2 - ch); ch < ch2; ++ch) {
|
||||
QFixed shift1 = QFixed(2 * (charsCount - (ch2 - ch)) + 2) * gwidth / QFixed(2 * charsCount),
|
||||
shift2 = QFixed(2 * (charsCount - (ch2 - ch)) + 1) * gwidth / QFixed(2 * charsCount);
|
||||
if ((rtl && _lnkX >= tmpx - shift1) ||
|
||||
(!rtl && _lnkX < tmpx + shift1)) {
|
||||
*_getSymbol = _localFrom + itemStart + ch;
|
||||
if ((rtl && _lnkX >= tmpx - shift2) ||
|
||||
(!rtl && _lnkX < tmpx + shift2)) {
|
||||
*_getSymbolAfter = false;
|
||||
} else {
|
||||
*_getSymbolAfter = true;
|
||||
}
|
||||
_lookupResult.uponSymbol = true;
|
||||
if (_lookupSymbol) {
|
||||
QFixed tmpx = rtl ? (x + itemWidth) : x;
|
||||
for (int ch = 0, g, itemL = itemEnd - itemStart; ch < itemL;) {
|
||||
g = logClusters[itemStart - si.position + ch];
|
||||
QFixed gwidth = glyphs.effectiveAdvance(g);
|
||||
// ch2 - glyph end, ch - glyph start, (ch2 - ch) - how much chars it takes
|
||||
int ch2 = ch + 1;
|
||||
while ((ch2 < itemL) && (g == logClusters[itemStart - si.position + ch2])) {
|
||||
++ch2;
|
||||
}
|
||||
for (int charsCount = (ch2 - ch); ch < ch2; ++ch) {
|
||||
QFixed shift1 = QFixed(2 * (charsCount - (ch2 - ch)) + 2) * gwidth / QFixed(2 * charsCount),
|
||||
shift2 = QFixed(2 * (charsCount - (ch2 - ch)) + 1) * gwidth / QFixed(2 * charsCount);
|
||||
if ((rtl && _lookupX >= tmpx - shift1) ||
|
||||
(!rtl && _lookupX < tmpx + shift1)) {
|
||||
_lookupResult.symbol = _localFrom + itemStart + ch;
|
||||
if ((rtl && _lookupX >= tmpx - shift2) ||
|
||||
(!rtl && _lookupX < tmpx + shift2)) {
|
||||
_lookupResult.afterSymbol = false;
|
||||
} else {
|
||||
_lookupResult.afterSymbol = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*_getSymbolUpon = true;
|
||||
return false;
|
||||
}
|
||||
if (rtl) {
|
||||
tmpx -= gwidth;
|
||||
} else {
|
||||
tmpx += gwidth;
|
||||
}
|
||||
}
|
||||
if (rtl) {
|
||||
tmpx -= gwidth;
|
||||
if (itemEnd > itemStart) {
|
||||
_lookupResult.symbol = _localFrom + itemEnd - 1;
|
||||
_lookupResult.afterSymbol = true;
|
||||
} else {
|
||||
tmpx += gwidth;
|
||||
_lookupResult.symbol = _localFrom + itemStart;
|
||||
_lookupResult.afterSymbol = false;
|
||||
}
|
||||
}
|
||||
if (itemEnd > itemStart) {
|
||||
*_getSymbol = _localFrom + itemEnd - 1;
|
||||
*_getSymbolAfter = true;
|
||||
} else {
|
||||
*_getSymbol = _localFrom + itemStart;
|
||||
*_getSymbolAfter = false;
|
||||
}
|
||||
*_getSymbolUpon = true;
|
||||
return false;
|
||||
} else if (_p) {
|
||||
#ifndef TDESKTOP_WINRT // temp
|
||||
|
@ -1564,12 +1563,12 @@ public:
|
|||
gf.justified = false;
|
||||
gf.initWithScriptItem(si);
|
||||
#endif // !TDESKTOP_WINRT
|
||||
if (_localFrom + itemStart < _selectedTo && _localFrom + itemEnd > _selectedFrom) {
|
||||
if (_localFrom + itemStart < _selection.to && _localFrom + itemEnd > _selection.from) {
|
||||
QFixed selX = x, selWidth = itemWidth;
|
||||
if (_localFrom + itemEnd > _selectedTo || _localFrom + itemStart < _selectedFrom) {
|
||||
if (_localFrom + itemEnd > _selection.to || _localFrom + itemStart < _selection.from) {
|
||||
selWidth = 0;
|
||||
int itemL = itemEnd - itemStart;
|
||||
int selStart = _selectedFrom - (_localFrom + itemStart), selEnd = _selectedTo - (_localFrom + itemStart);
|
||||
int selStart = _selection.from - (_localFrom + itemStart), selEnd = _selection.to - (_localFrom + itemStart);
|
||||
if (selStart < 0) selStart = 0;
|
||||
if (selEnd > itemL) selEnd = itemL;
|
||||
for (int ch = 0, g; ch < selEnd;) {
|
||||
|
@ -1675,6 +1674,7 @@ public:
|
|||
if (_wLeft < si.width) {
|
||||
lineText = lineText.mid(0, currentBlock->from() - _localFrom) + _Elide;
|
||||
lineLength = currentBlock->from() + _Elide.size() - _lineStart;
|
||||
_selection.to = std::min({ _selection.to, currentBlock->from() });
|
||||
setElideBidi(currentBlock->from(), _Elide.size());
|
||||
elideSaveBlock(blockIndex - 1, _endBlock, currentBlock->from(), elideWidth);
|
||||
return;
|
||||
|
@ -1706,6 +1706,7 @@ public:
|
|||
if (lineText.size() <= pos || repeat > 3) {
|
||||
lineText += _Elide;
|
||||
lineLength = _localFrom + pos + _Elide.size() - _lineStart;
|
||||
_selection.to = std::min({ _selection.to, uint16(_localFrom + pos) });
|
||||
setElideBidi(_localFrom + pos, _Elide.size());
|
||||
_blocksSize = blockIndex;
|
||||
_endBlock = nextBlock;
|
||||
|
@ -1724,7 +1725,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int32 elideStart = _lineStart + lineText.length();
|
||||
int32 elideStart = _localFrom + lineText.size();
|
||||
_selection.to = std::min({ _selection.to, uint16(elideStart) });
|
||||
setElideBidi(elideStart, _Elide.size());
|
||||
|
||||
lineText += _Elide;
|
||||
|
@ -2369,13 +2371,14 @@ private:
|
|||
|
||||
QPainter *_p;
|
||||
const Text *_t;
|
||||
bool _elideLast, _breakEverywhere;
|
||||
int32 _elideRemoveFromEnd;
|
||||
bool _elideLast = false;
|
||||
bool _breakEverywhere = false;
|
||||
int32 _elideRemoveFromEnd = 0;
|
||||
style::align _align;
|
||||
QPen _originalPen;
|
||||
int32 _yFrom, _yTo, _yToElide;
|
||||
uint16 _selectedFrom, _selectedTo;
|
||||
const QChar *_str;
|
||||
TextSelection _selection = { 0, 0 };
|
||||
const QChar *_str = nullptr;
|
||||
|
||||
// current paragraph data
|
||||
Text::TextBlocks::const_iterator _parStartBlock;
|
||||
|
@ -2393,18 +2396,18 @@ private:
|
|||
// elided hack support
|
||||
int32 _blocksSize;
|
||||
int32 _elideSavedIndex;
|
||||
ITextBlock *_elideSavedBlock;
|
||||
ITextBlock *_elideSavedBlock = nullptr;
|
||||
|
||||
int32 _lineStart, _localFrom;
|
||||
int32 _lineStartBlock;
|
||||
|
||||
// link and symbol resolve
|
||||
QFixed _lnkX;
|
||||
int32 _lnkY;
|
||||
const ClickHandlerPtr *_lnkResult;
|
||||
bool *_inTextFlag;
|
||||
uint16 *_getSymbol;
|
||||
bool *_getSymbolAfter, *_getSymbolUpon;
|
||||
QFixed _lookupX = 0;
|
||||
int _lookupY = 0;
|
||||
bool _lookupSymbol = false;
|
||||
bool _lookupLink = false;
|
||||
Text::StateRequest _lookupRequest;
|
||||
Text::StateResult _lookupResult;
|
||||
|
||||
};
|
||||
|
||||
|
@ -2935,36 +2938,32 @@ void Text::replaceFont(style::font f) {
|
|||
_font = f;
|
||||
}
|
||||
|
||||
void Text::draw(QPainter &painter, int32 left, int32 top, int32 w, style::align align, int32 yFrom, int32 yTo, uint16 selectedFrom, uint16 selectedTo) const {
|
||||
void Text::draw(QPainter &painter, int32 left, int32 top, int32 w, style::align align, int32 yFrom, int32 yTo, TextSelection selection) const {
|
||||
// painter.fillRect(QRect(left, top, w, countHeight(w)), QColor(0, 0, 0, 32)); // debug
|
||||
TextPainter p(&painter, this);
|
||||
p.draw(left, top, w, align, yFrom, yTo, selectedFrom, selectedTo);
|
||||
p.draw(left, top, w, align, yFrom, yTo, selection);
|
||||
}
|
||||
|
||||
void Text::drawElided(QPainter &painter, int32 left, int32 top, int32 w, int32 lines, style::align align, int32 yFrom, int32 yTo, int32 removeFromEnd, bool breakEverywhere) const {
|
||||
void Text::drawElided(QPainter &painter, int32 left, int32 top, int32 w, int32 lines, style::align align, int32 yFrom, int32 yTo, int32 removeFromEnd, bool breakEverywhere, TextSelection selection) const {
|
||||
// painter.fillRect(QRect(left, top, w, countHeight(w)), QColor(0, 0, 0, 32)); // debug
|
||||
TextPainter p(&painter, this);
|
||||
p.drawElided(left, top, w, align, lines, yFrom, yTo, removeFromEnd, breakEverywhere);
|
||||
p.drawElided(left, top, w, align, lines, yFrom, yTo, removeFromEnd, breakEverywhere, selection);
|
||||
}
|
||||
|
||||
const ClickHandlerPtr &Text::link(int32 x, int32 y, int32 width, style::align align) const {
|
||||
Text::StateResult Text::getState(int x, int y, int width, StateRequest request) const {
|
||||
TextPainter p(0, this);
|
||||
return p.link(x, y, width, align);
|
||||
return p.getState(x, y, width, request);
|
||||
}
|
||||
|
||||
void Text::getState(ClickHandlerPtr &lnk, bool &inText, int32 x, int32 y, int32 width, style::align align, bool breakEverywhere) const {
|
||||
Text::StateResult Text::getStateElided(int x, int y, int width, StateRequestElided request) const {
|
||||
TextPainter p(0, this);
|
||||
p.getState(lnk, inText, x, y, width, align, breakEverywhere);
|
||||
return p.getStateElided(x, y, width, request);
|
||||
}
|
||||
|
||||
void Text::getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 width, style::align align) const {
|
||||
TextPainter p(0, this);
|
||||
p.getSymbol(symbol, after, upon, x, y, width, align);
|
||||
}
|
||||
|
||||
uint32 Text::adjustSelection(uint16 from, uint16 to, TextSelectType selectType) const {
|
||||
TextSelection Text::adjustSelection(TextSelection selection, TextSelectType selectType) const {
|
||||
uint16 from = selection.from, to = selection.to;
|
||||
if (from < _text.size() && from <= to) {
|
||||
if (to > _text.size()) to = _text.size() - 1;
|
||||
if (to > _text.size()) to = _text.size();
|
||||
if (selectType == TextSelectParagraphs) {
|
||||
if (!chIsParagraphSeparator(_text.at(from))) {
|
||||
while (from > 0 && !chIsParagraphSeparator(_text.at(from - 1))) {
|
||||
|
@ -2997,10 +2996,10 @@ uint32 Text::adjustSelection(uint16 from, uint16 to, TextSelectType selectType)
|
|||
}
|
||||
}
|
||||
}
|
||||
return (from << 16) | to;
|
||||
return { from, to };
|
||||
}
|
||||
|
||||
QString Text::original(uint16 selectedFrom, uint16 selectedTo, ExpandLinksMode mode) const {
|
||||
QString Text::original(TextSelection selection, ExpandLinksMode mode) const {
|
||||
QString result, emptyurl;
|
||||
result.reserve(_text.size());
|
||||
|
||||
|
@ -3013,7 +3012,7 @@ QString Text::original(uint16 selectedFrom, uint16 selectedTo, ExpandLinksMode m
|
|||
const ClickHandlerPtr &lnk(_links.at(lnkIndex - 1));
|
||||
const QString &url = (mode == ExpandLinksNone || !lnk) ? emptyurl : lnk->text();
|
||||
|
||||
int32 rangeFrom = qMax(int32(selectedFrom), lnkFrom), rangeTo = qMin(blockFrom, int32(selectedTo));
|
||||
int32 rangeFrom = qMax(int32(selection.from), lnkFrom), rangeTo = qMin(blockFrom, int32(selection.to));
|
||||
|
||||
if (rangeTo > rangeFrom) {
|
||||
QStringRef r = _text.midRef(rangeFrom, rangeTo - rangeFrom);
|
||||
|
@ -3043,7 +3042,7 @@ QString Text::original(uint16 selectedFrom, uint16 selectedTo, ExpandLinksMode m
|
|||
if (type == TextBlockTSkip) continue;
|
||||
|
||||
if (!blockLnkIndex) {
|
||||
int32 rangeFrom = qMax(selectedFrom, (*i)->from()), rangeTo = qMin(selectedTo, uint16((*i)->from() + TextPainter::_blockLength(this, i, e)));
|
||||
int32 rangeFrom = qMax(selection.from, (*i)->from()), rangeTo = qMin(selection.to, uint16((*i)->from() + TextPainter::_blockLength(this, i, e)));
|
||||
if (rangeTo > rangeFrom) {
|
||||
result += _text.midRef(rangeFrom, rangeTo - rangeFrom);
|
||||
}
|
||||
|
|
|
@ -344,6 +344,23 @@ enum TextSelectType {
|
|||
TextSelectParagraphs = 0x03,
|
||||
};
|
||||
|
||||
struct TextSelection {
|
||||
constexpr TextSelection() : from(0), to(0) {
|
||||
}
|
||||
constexpr TextSelection(uint16 from, uint16 to) : from(from), to(to) {
|
||||
}
|
||||
uint16 from : 16;
|
||||
uint16 to : 16;
|
||||
};
|
||||
inline bool operator==(TextSelection a, TextSelection b) {
|
||||
return a.from == b.from && a.to == b.to;
|
||||
}
|
||||
inline bool operator!=(TextSelection a, TextSelection b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
static constexpr TextSelection AllTextSelection = { 0, 0xFFFF };
|
||||
|
||||
typedef QPair<QString, QString> TextCustomTag; // open str and close str
|
||||
typedef QMap<QChar, TextCustomTag> TextCustomTagsMap;
|
||||
|
||||
|
@ -381,34 +398,55 @@ public:
|
|||
|
||||
void replaceFont(style::font f); // does not recount anything, use at your own risk!
|
||||
|
||||
void draw(QPainter &p, int32 left, int32 top, int32 width, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const;
|
||||
void drawElided(QPainter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false) const;
|
||||
void drawLeft(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const {
|
||||
draw(p, rtl() ? (outerw - left - width) : left, top, width, align, yFrom, yTo, selectedFrom, selectedTo);
|
||||
void draw(QPainter &p, int32 left, int32 top, int32 width, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, TextSelection selection = { 0, 0 }) const;
|
||||
void drawElided(QPainter &p, int32 left, int32 top, int32 width, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false, TextSelection selection = { 0, 0 }) const;
|
||||
void drawLeft(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, TextSelection selection = { 0, 0 }) const {
|
||||
draw(p, rtl() ? (outerw - left - width) : left, top, width, align, yFrom, yTo, selection);
|
||||
}
|
||||
void drawLeftElided(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false) const {
|
||||
drawElided(p, rtl() ? (outerw - left - width) : left, top, width, lines, align, yFrom, yTo, removeFromEnd, breakEverywhere);
|
||||
void drawLeftElided(QPainter &p, int32 left, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false, TextSelection selection = { 0, 0 }) const {
|
||||
drawElided(p, rtl() ? (outerw - left - width) : left, top, width, lines, align, yFrom, yTo, removeFromEnd, breakEverywhere, selection);
|
||||
}
|
||||
void drawRight(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, uint16 selectedFrom = 0, uint16 selectedTo = 0) const {
|
||||
draw(p, rtl() ? right : (outerw - right - width), top, width, align, yFrom, yTo, selectedFrom, selectedTo);
|
||||
void drawRight(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, TextSelection selection = { 0, 0 }) const {
|
||||
draw(p, rtl() ? right : (outerw - right - width), top, width, align, yFrom, yTo, selection);
|
||||
}
|
||||
void drawRightElided(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false) const {
|
||||
drawElided(p, rtl() ? right : (outerw - right - width), top, width, lines, align, yFrom, yTo, removeFromEnd, breakEverywhere);
|
||||
void drawRightElided(QPainter &p, int32 right, int32 top, int32 width, int32 outerw, int32 lines = 1, style::align align = style::al_left, int32 yFrom = 0, int32 yTo = -1, int32 removeFromEnd = 0, bool breakEverywhere = false, TextSelection selection = { 0, 0 }) const {
|
||||
drawElided(p, rtl() ? right : (outerw - right - width), top, width, lines, align, yFrom, yTo, removeFromEnd, breakEverywhere, selection);
|
||||
}
|
||||
|
||||
const ClickHandlerPtr &link(int32 x, int32 y, int32 width, style::align align = style::al_left) const;
|
||||
const ClickHandlerPtr &linkLeft(int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left) const {
|
||||
return link(rtl() ? (outerw - x - width) : x, y, width, align);
|
||||
struct StateRequest {
|
||||
enum class Flag {
|
||||
BreakEverywhere = 0x01,
|
||||
LookupSymbol = 0x02,
|
||||
LookupLink = 0x04,
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag);
|
||||
|
||||
style::align align = style::al_left;
|
||||
Flags flags = Flag::LookupLink;
|
||||
};
|
||||
struct StateResult {
|
||||
ClickHandlerPtr link;
|
||||
bool uponSymbol = false;
|
||||
bool afterSymbol = false;
|
||||
uint16 symbol = 0;
|
||||
};
|
||||
StateResult getState(int x, int y, int width, StateRequest request = StateRequest()) const;
|
||||
StateResult getStateLeft(int x, int y, int width, int outerw, StateRequest request = StateRequest()) const {
|
||||
return getState(rtl() ? (outerw - x - width) : x, y, width, request);
|
||||
}
|
||||
void getState(ClickHandlerPtr &lnk, bool &inText, int32 x, int32 y, int32 width, style::align align = style::al_left, bool breakEverywhere = false) const;
|
||||
void getStateLeft(ClickHandlerPtr &lnk, bool &inText, int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left, bool breakEverywhere = false) const {
|
||||
return getState(lnk, inText, rtl() ? (outerw - x - width) : x, y, width, align, breakEverywhere);
|
||||
struct StateRequestElided : public StateRequest {
|
||||
StateRequestElided() = default;
|
||||
StateRequestElided(const StateRequest &other) : StateRequest(other) {
|
||||
}
|
||||
int lines = 1;
|
||||
int removeFromEnd = 0;
|
||||
};
|
||||
StateResult getStateElided(int x, int y, int width, StateRequestElided request = StateRequestElided()) const;
|
||||
StateResult getStateElidedLeft(int x, int y, int width, int outerw, StateRequestElided request = StateRequestElided()) const {
|
||||
return getStateElided(rtl() ? (outerw - x - width) : x, y, width, request);
|
||||
}
|
||||
void getSymbol(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 width, style::align align = style::al_left) const;
|
||||
void getSymbolLeft(uint16 &symbol, bool &after, bool &upon, int32 x, int32 y, int32 width, int32 outerw, style::align align = style::al_left) const {
|
||||
return getSymbol(symbol, after, upon, rtl() ? (outerw - x - width) : x, y, width, align);
|
||||
}
|
||||
uint32 adjustSelection(uint16 from, uint16 to, TextSelectType selectType) const;
|
||||
|
||||
TextSelection adjustSelection(TextSelection selection, TextSelectType selectType) const;
|
||||
|
||||
bool isEmpty() const {
|
||||
return _text.isEmpty();
|
||||
|
@ -416,12 +454,15 @@ public:
|
|||
bool isNull() const {
|
||||
return !_font;
|
||||
}
|
||||
int length() const {
|
||||
return _text.size();
|
||||
}
|
||||
enum ExpandLinksMode {
|
||||
ExpandLinksNone,
|
||||
ExpandLinksShortened,
|
||||
ExpandLinksAll,
|
||||
};
|
||||
QString original(uint16 selectedFrom = 0, uint16 selectedTo = 0xFFFF, ExpandLinksMode mode = ExpandLinksShortened) const;
|
||||
QString original(TextSelection selection = { 0, 0xFFFF }, ExpandLinksMode mode = ExpandLinksShortened) const;
|
||||
EntitiesInText originalEntities() const;
|
||||
|
||||
bool lastDots(int32 dots, int32 maxdots = 3) { // hack for typing animation
|
||||
|
@ -474,6 +515,17 @@ private:
|
|||
friend class TextPainter;
|
||||
|
||||
};
|
||||
inline TextSelection snapSelection(int from, int to) {
|
||||
return { static_cast<uint16>(snap(from, 0, 0xFFFF)), static_cast<uint16>(snap(to, 0, 0xFFFF)) };
|
||||
}
|
||||
inline TextSelection shiftSelection(TextSelection selection, const Text &byText) {
|
||||
int len = byText.length();
|
||||
return snapSelection(int(selection.from) + len, int(selection.to) + len);
|
||||
}
|
||||
inline TextSelection unshiftSelection(TextSelection selection, const Text &byText) {
|
||||
int len = byText.length();
|
||||
return snapSelection(int(selection.from) - len, int(selection.to) - len);
|
||||
}
|
||||
|
||||
void initLinkSets();
|
||||
const QSet<int32> &validProtocols();
|
||||
|
|
Loading…
Add table
Reference in a new issue