mirror of
https://github.com/vale981/tdesktop
synced 2025-03-08 19:21:39 -05:00
Dragging text from FlatLabel is supported.
Started drag-n-drop support for chat photo updating.
This commit is contained in:
parent
ab59ef8498
commit
329285a8a6
6 changed files with 118 additions and 4 deletions
|
@ -457,6 +457,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
||||||
"lng_profile_shared_links_header" = "Shared links overview";
|
"lng_profile_shared_links_header" = "Shared links overview";
|
||||||
"lng_profile_copy_phone" = "Copy phone number";
|
"lng_profile_copy_phone" = "Copy phone number";
|
||||||
"lng_profile_copy_fullname" = "Copy name";
|
"lng_profile_copy_fullname" = "Copy name";
|
||||||
|
"lng_profile_drop_area_title" = "Drop your image here";
|
||||||
|
"lng_profile_drop_area_subtitle" = "to set it as a group photo";
|
||||||
|
|
||||||
"lng_channel_add_admins" = "New administrator";
|
"lng_channel_add_admins" = "New administrator";
|
||||||
"lng_channel_add_members" = "Add members";
|
"lng_channel_add_members" = "Add members";
|
||||||
|
|
|
@ -76,6 +76,16 @@ profileSecondaryButton: BoxButton(profilePrimaryButton) {
|
||||||
textBgOver: #f2f7fa;
|
textBgOver: #f2f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profileDropAreaBg: profileBg;
|
||||||
|
profileDropAreaFg: #3fb0e4;
|
||||||
|
profileDropAreaPadding: margins(30px, 20px, 30px, 20px);
|
||||||
|
profileDropAreaTitleFont: font(24px);
|
||||||
|
profileDropAreaTitleTop: 36px;
|
||||||
|
profileDropAreaSubtitleFont: font(16px);
|
||||||
|
profileDropAreaSubtitleTop: 72px;
|
||||||
|
profileDropAreaBorderFg: profileDropAreaFg;
|
||||||
|
profileDropAreaBorderWidth: 3px;
|
||||||
|
|
||||||
profileDividerFg: black;
|
profileDividerFg: black;
|
||||||
profileDividerLeft: icon {
|
profileDividerLeft: icon {
|
||||||
{ "profile_divider_left", profileDividerFg },
|
{ "profile_divider_left", profileDividerFg },
|
||||||
|
|
|
@ -123,6 +123,50 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DropArea : public TWidget {
|
||||||
|
public:
|
||||||
|
DropArea(QWidget *parent) : TWidget(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void showAnimated() {
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override {
|
||||||
|
Painter p(this);
|
||||||
|
p.fillRect(e->rect(), st::profileDropAreaBg);
|
||||||
|
|
||||||
|
if (width() < st::profileDropAreaPadding.left() + st::profileDropAreaPadding.right()) return;
|
||||||
|
if (height() < st::profileDropAreaPadding.top() + st::profileDropAreaPadding.bottom()) return;
|
||||||
|
|
||||||
|
auto border = st::profileDropAreaBorderWidth;
|
||||||
|
auto &borderFg = st::profileDropAreaBorderFg;
|
||||||
|
auto inner = rect().marginsRemoved(st::profileDropAreaPadding);
|
||||||
|
p.fillRect(inner.x(), inner.y(), inner.width(), border, borderFg);
|
||||||
|
p.fillRect(inner.x(), inner.y() + inner.height() - border, inner.width(), border, borderFg);
|
||||||
|
p.fillRect(inner.x(), inner.y() + border, border, inner.height() - 2 * border, borderFg);
|
||||||
|
p.fillRect(inner.x() + inner.width() - border, inner.y() + border, border, inner.height() - 2 * border, borderFg);
|
||||||
|
|
||||||
|
auto title = lang(lng_profile_drop_area_title);
|
||||||
|
int titleWidth = st::profileDropAreaTitleFont->width(title);
|
||||||
|
int titleLeft = inner.x() + (inner.width() - titleWidth) / 2;
|
||||||
|
int titleTop = inner.y() + st::profileDropAreaTitleTop + st::profileDropAreaTitleFont->ascent;
|
||||||
|
p.setFont(st::profileDropAreaTitleFont);
|
||||||
|
p.setPen(st::profileDropAreaFg);
|
||||||
|
p.drawText(titleLeft, titleTop, title);
|
||||||
|
|
||||||
|
auto subtitle = lang(lng_profile_drop_area_subtitle);
|
||||||
|
int subtitleWidth = st::profileDropAreaSubtitleFont->width(subtitle);
|
||||||
|
int subtitleLeft = inner.x() + (inner.width() - subtitleWidth) / 2;
|
||||||
|
int subtitleTop = inner.y() + st::profileDropAreaSubtitleTop + st::profileDropAreaSubtitleFont->ascent;
|
||||||
|
p.setFont(st::profileDropAreaSubtitleFont);
|
||||||
|
p.setPen(st::profileDropAreaFg);
|
||||||
|
p.drawText(subtitleLeft, subtitleTop, subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent)
|
CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent)
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
, _peerUser(peer->asUser())
|
, _peerUser(peer->asUser())
|
||||||
|
@ -132,6 +176,7 @@ CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent)
|
||||||
, _photoButton(this, peer)
|
, _photoButton(this, peer)
|
||||||
, _name(this, QString(), st::profileNameLabel) {
|
, _name(this, QString(), st::profileNameLabel) {
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
_name.setSelectable(true);
|
_name.setSelectable(true);
|
||||||
_name.setContextCopyText(lang(lng_profile_copy_fullname));
|
_name.setContextCopyText(lang(lng_profile_copy_fullname));
|
||||||
|
@ -204,6 +249,23 @@ void CoverWidget::paintEvent(QPaintEvent *e) {
|
||||||
paintDivider(p);
|
paintDivider(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CoverWidget::dragEnterEvent(QDragEnterEvent *e) {
|
||||||
|
_dropArea = new DropArea(this);
|
||||||
|
_dropArea->setGeometry(0, 0, width(), _dividerTop);
|
||||||
|
_dropArea->showAnimated();
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoverWidget::dragLeaveEvent(QDragLeaveEvent *e) {
|
||||||
|
delete _dropArea;
|
||||||
|
_dropArea = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoverWidget::dropEvent(QDropEvent *e) {
|
||||||
|
delete _dropArea;
|
||||||
|
_dropArea = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void CoverWidget::paintDivider(Painter &p) {
|
void CoverWidget::paintDivider(Painter &p) {
|
||||||
st::profileDividerLeft.paint(p, QPoint(st::lineWidth, _dividerTop), width());
|
st::profileDividerLeft.paint(p, QPoint(st::lineWidth, _dividerTop), width());
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace Profile {
|
||||||
|
|
||||||
class BackButton;
|
class BackButton;
|
||||||
class PhotoButton;
|
class PhotoButton;
|
||||||
|
class DropArea;
|
||||||
|
|
||||||
class CoverWidget final : public TWidget, public Notify::Observer {
|
class CoverWidget final : public TWidget, public Notify::Observer {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -58,6 +59,9 @@ private slots:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent *e) override;
|
||||||
|
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||||
|
void dropEvent(QDropEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Observed notifications.
|
// Observed notifications.
|
||||||
|
@ -85,8 +89,8 @@ private:
|
||||||
ChannelData *_peerChannel;
|
ChannelData *_peerChannel;
|
||||||
ChannelData *_peerMegagroup;
|
ChannelData *_peerMegagroup;
|
||||||
|
|
||||||
// Cover content
|
|
||||||
ChildWidget<PhotoButton> _photoButton;
|
ChildWidget<PhotoButton> _photoButton;
|
||||||
|
ChildWidget<DropArea> _dropArea = { nullptr };
|
||||||
|
|
||||||
FlatLabel _name;
|
FlatLabel _name;
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@ Text::StateResult FlatLabel::dragActionStart(const QPoint &p, Qt::MouseButton bu
|
||||||
if (_dragWasInactive) App::wnd()->inactivePress(false);
|
if (_dragWasInactive) App::wnd()->inactivePress(false);
|
||||||
|
|
||||||
if (ClickHandler::getPressed()) {
|
if (ClickHandler::getPressed()) {
|
||||||
|
_dragStartPosition = mapFromGlobal(_lastMousePos);
|
||||||
_dragAction = PrepareDrag;
|
_dragAction = PrepareDrag;
|
||||||
}
|
}
|
||||||
if (!_selectable || _dragAction != NoDrag) {
|
if (!_selectable || _dragAction != NoDrag) {
|
||||||
|
@ -147,6 +148,7 @@ Text::StateResult FlatLabel::dragActionStart(const QPoint &p, Qt::MouseButton bu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uponSelected) {
|
if (uponSelected) {
|
||||||
|
_dragStartPosition = mapFromGlobal(_lastMousePos);
|
||||||
_dragAction = PrepareDrag; // start text drag
|
_dragAction = PrepareDrag; // start text drag
|
||||||
} else if (!_dragWasInactive) {
|
} else if (!_dragWasInactive) {
|
||||||
if (state.afterSymbol) ++_dragSymbol;
|
if (state.afterSymbol) ++_dragSymbol;
|
||||||
|
@ -391,6 +393,33 @@ void FlatLabel::onContextMenuDestroy(QObject *obj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FlatLabel::onExecuteDrag() {
|
||||||
|
if (_dragAction != Dragging) return;
|
||||||
|
|
||||||
|
auto state = getTextState(_dragStartPosition);
|
||||||
|
bool uponSelected = state.uponSymbol && _selection.from <= state.symbol;
|
||||||
|
if (uponSelected) {
|
||||||
|
if (_dragSymbol < _selection.from || _dragSymbol >= _selection.to) {
|
||||||
|
uponSelected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr pressedHandler = ClickHandler::getPressed();
|
||||||
|
QString selectedText;
|
||||||
|
if (uponSelected) {
|
||||||
|
selectedText = _text.originalText(_selection, ExpandLinksAll);
|
||||||
|
} else if (pressedHandler) {
|
||||||
|
selectedText = pressedHandler->dragText();
|
||||||
|
}
|
||||||
|
if (!selectedText.isEmpty()) {
|
||||||
|
auto mimeData = new QMimeData();
|
||||||
|
mimeData->setText(selectedText);
|
||||||
|
auto drag = new QDrag(App::wnd());
|
||||||
|
drag->setMimeData(mimeData);
|
||||||
|
drag->exec(Qt::CopyAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FlatLabel::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
void FlatLabel::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -400,10 +429,15 @@ void FlatLabel::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool a
|
||||||
}
|
}
|
||||||
|
|
||||||
Text::StateResult FlatLabel::dragActionUpdate() {
|
Text::StateResult FlatLabel::dragActionUpdate() {
|
||||||
QPoint m(mapFromGlobal(_lastMousePos));
|
auto m = mapFromGlobal(_lastMousePos);
|
||||||
LOG(("DRAG ACTION UPDATE: %1 %2").arg(m.x()).arg(m.y()));
|
|
||||||
auto state = getTextState(m);
|
auto state = getTextState(m);
|
||||||
updateHover(state);
|
updateHover(state);
|
||||||
|
|
||||||
|
if (_dragAction == PrepareDrag && (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
|
||||||
|
_dragAction = Dragging;
|
||||||
|
QTimer::singleShot(1, this, SLOT(onExecuteDrag()));
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ private slots:
|
||||||
void onTouchSelect();
|
void onTouchSelect();
|
||||||
void onContextMenuDestroy(QObject *obj);
|
void onContextMenuDestroy(QObject *obj);
|
||||||
|
|
||||||
|
void onExecuteDrag();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Text::StateResult dragActionUpdate();
|
Text::StateResult dragActionUpdate();
|
||||||
Text::StateResult dragActionStart(const QPoint &p, Qt::MouseButton button);
|
Text::StateResult dragActionStart(const QPoint &p, Qt::MouseButton button);
|
||||||
|
@ -100,10 +102,10 @@ private:
|
||||||
NoDrag = 0x00,
|
NoDrag = 0x00,
|
||||||
PrepareDrag = 0x01,
|
PrepareDrag = 0x01,
|
||||||
Dragging = 0x02,
|
Dragging = 0x02,
|
||||||
PrepareSelect = 0x03,
|
|
||||||
Selecting = 0x04,
|
Selecting = 0x04,
|
||||||
};
|
};
|
||||||
DragAction _dragAction = NoDrag;
|
DragAction _dragAction = NoDrag;
|
||||||
|
QPoint _dragStartPosition;
|
||||||
uint16 _dragSymbol = 0;
|
uint16 _dragSymbol = 0;
|
||||||
bool _dragWasInactive = false;
|
bool _dragWasInactive = false;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue