Dragging text from FlatLabel is supported.

Started drag-n-drop support for chat photo updating.
This commit is contained in:
John Preston 2016-05-26 19:05:39 +03:00
parent ab59ef8498
commit 329285a8a6
6 changed files with 118 additions and 4 deletions

View File

@ -457,6 +457,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_profile_shared_links_header" = "Shared links overview";
"lng_profile_copy_phone" = "Copy phone number";
"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_members" = "Add members";

View File

@ -76,6 +76,16 @@ profileSecondaryButton: BoxButton(profilePrimaryButton) {
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;
profileDividerLeft: icon {
{ "profile_divider_left", profileDividerFg },

View File

@ -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)
, _peer(peer)
, _peerUser(peer->asUser())
@ -132,6 +176,7 @@ CoverWidget::CoverWidget(QWidget *parent, PeerData *peer) : TWidget(parent)
, _photoButton(this, peer)
, _name(this, QString(), st::profileNameLabel) {
setAttribute(Qt::WA_OpaquePaintEvent);
setAcceptDrops(true);
_name.setSelectable(true);
_name.setContextCopyText(lang(lng_profile_copy_fullname));
@ -204,6 +249,23 @@ void CoverWidget::paintEvent(QPaintEvent *e) {
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) {
st::profileDividerLeft.paint(p, QPoint(st::lineWidth, _dividerTop), width());

View File

@ -36,6 +36,7 @@ namespace Profile {
class BackButton;
class PhotoButton;
class DropArea;
class CoverWidget final : public TWidget, public Notify::Observer {
Q_OBJECT
@ -58,6 +59,9 @@ private slots:
protected:
void paintEvent(QPaintEvent *e) override;
void dragEnterEvent(QDragEnterEvent *e) override;
void dragLeaveEvent(QDragLeaveEvent *e) override;
void dropEvent(QDropEvent *e) override;
private:
// Observed notifications.
@ -85,8 +89,8 @@ private:
ChannelData *_peerChannel;
ChannelData *_peerMegagroup;
// Cover content
ChildWidget<PhotoButton> _photoButton;
ChildWidget<DropArea> _dropArea = { nullptr };
FlatLabel _name;

View File

@ -120,6 +120,7 @@ Text::StateResult FlatLabel::dragActionStart(const QPoint &p, Qt::MouseButton bu
if (_dragWasInactive) App::wnd()->inactivePress(false);
if (ClickHandler::getPressed()) {
_dragStartPosition = mapFromGlobal(_lastMousePos);
_dragAction = PrepareDrag;
}
if (!_selectable || _dragAction != NoDrag) {
@ -147,6 +148,7 @@ Text::StateResult FlatLabel::dragActionStart(const QPoint &p, Qt::MouseButton bu
}
}
if (uponSelected) {
_dragStartPosition = mapFromGlobal(_lastMousePos);
_dragAction = PrepareDrag; // start text drag
} else if (!_dragWasInactive) {
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) {
update();
}
@ -400,10 +429,15 @@ void FlatLabel::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool a
}
Text::StateResult FlatLabel::dragActionUpdate() {
QPoint m(mapFromGlobal(_lastMousePos));
LOG(("DRAG ACTION UPDATE: %1 %2").arg(m.x()).arg(m.y()));
auto m = mapFromGlobal(_lastMousePos);
auto state = getTextState(m);
updateHover(state);
if (_dragAction == PrepareDrag && (m - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) {
_dragAction = Dragging;
QTimer::singleShot(1, this, SLOT(onExecuteDrag()));
}
return state;
}

View File

@ -64,6 +64,8 @@ private slots:
void onTouchSelect();
void onContextMenuDestroy(QObject *obj);
void onExecuteDrag();
private:
Text::StateResult dragActionUpdate();
Text::StateResult dragActionStart(const QPoint &p, Qt::MouseButton button);
@ -100,10 +102,10 @@ private:
NoDrag = 0x00,
PrepareDrag = 0x01,
Dragging = 0x02,
PrepareSelect = 0x03,
Selecting = 0x04,
};
DragAction _dragAction = NoDrag;
QPoint _dragStartPosition;
uint16 _dragSymbol = 0;
bool _dragWasInactive = false;