Radial progress in settings when loading a new background from gallery.

MediaView handling of screen resolution change fixed.
Media messages now display both name/type and caption in dialogs list.
When viewing group profile photo delete affects either photo or message.
This commit is contained in:
John Preston 2016-06-22 16:39:54 +03:00
parent 6af6ffa1b2
commit 5957382a67
14 changed files with 462 additions and 236 deletions

View File

@ -16,6 +16,23 @@ index eec9e1f..ec3015e 100644
QMAKE_CFLAGS_YACC =
QMAKE_CFLAGS_LTCG = -GL
QMAKE_CFLAGS_SSE2 = -arch:SSE2
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index f1a6019..81ff6ef 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -1416,8 +1416,10 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst
COPYFILE2_EXTENDED_PARAMETERS copyParams = {
sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL
};
- bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(),
- (const wchar_t*)target.nativeFilePath().utf16(), &copyParams) != 0;
+ // CopyFile2 returns HRESULT, not BOOL, so it should be tested for S_OK, not 0.
+ HRESULT hres = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(),
+ (const wchar_t*)target.nativeFilePath().utf16(), &copyParams);
+ bool ret = SUCCEEDED(hres);
#endif // Q_OS_WINRT
if(!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp
index 14e4fd1..c31c62b 100644
--- a/src/corelib/tools/qunicodetables.cpp
@ -82,14 +99,14 @@ index 918c989..55ef783 100644
+#endif
+ }
}
// Make sure we're inside the viewport.
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 39c228f..b72fdc0 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -283,7 +283,8 @@ private:
struct QScriptItem;
/// Internal QTextItem
-class QTextItemInt : public QTextItem
@ -119,14 +136,14 @@ index 9e2a23a..4466a4e 100644
- while (oldPos < len && attributes[oldPos].whiteSpace)
- oldPos++;
}
return oldPos;
@@ -1644,6 +1645,7 @@ namespace {
int maxGlyphs;
int currentPosition;
glyph_t previousGlyph;
+ QFontEngine *previousGlyphFontEngine;
QFixed minw;
QFixed softHyphenWidth;
@@ -1677,13 +1679,14 @@ namespace {
@ -136,14 +153,14 @@ index 9e2a23a..4466a4e 100644
+ previousGlyphFontEngine = fontEngine;
}
}
- inline void calculateRightBearing(glyph_t glyph)
+ inline void calculateRightBearing(QFontEngine *engine, glyph_t glyph)
{
qreal rb;
- fontEngine->getGlyphBearings(glyph, 0, &rb);
+ engine->getGlyphBearings(glyph, 0, &rb);
// We only care about negative right bearings, so we limit the range
// of the bearing here so that we can assume it's negative in the rest
@@ -1696,13 +1699,13 @@ namespace {
@ -153,14 +170,14 @@ index 9e2a23a..4466a4e 100644
- calculateRightBearing(currentGlyph());
+ calculateRightBearing(fontEngine, currentGlyph());
}
inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
- calculateRightBearing(previousGlyph);
+ calculateRightBearing(previousGlyphFontEngine, previousGlyph);
}
static const QFixed RightBearingNotCalculated;
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index f74d4d4..57d449a 100644
@ -174,8 +191,8 @@ index f74d4d4..57d449a 100644
+ // allow access to private constructor
+ friend class TextBlock;
};
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index ca0a8b9..26ee865 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
@ -199,9 +216,9 @@ index 728b166..12364db 100644
--- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp
@@ -172,6 +172,79 @@ void QBasicFontDatabase::releaseHandle(void *handle)
extern FT_Library qt_getFreetype();
+// Enable Open Sans Semibold font family reading.
+// Copied from freetype with some modifications.
+
@ -295,9 +312,9 @@ index a5fe888..5878a4f 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -381,6 +381,17 @@ static void populateFromPattern(FcPattern *pattern)
familyName = QString::fromUtf8((const char *)value);
+ // Enable Open Sans Semibold font family reading.
+ if (familyName == QLatin1String("Open Sans")) {
+ FcChar8 *styl = 0;
@ -356,7 +373,7 @@ index 0af7790..c16f154 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -259,6 +259,13 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
fd->foundryName = QStringLiteral("CoreText");
fd->familyName = (CFStringRef) CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute);
+
@ -11193,13 +11210,13 @@ index faea54b..7d85080 100644
+++ b/src/plugins/platforminputcontexts/platforminputcontexts.pro
@@ -1,7 +1,8 @@
TEMPLATE = subdirs
qtHaveModule(dbus) {
-!mac:!win32:SUBDIRS += ibus
+# Adding fcitx input context plugin to our static build.
+!mac:!win32:SUBDIRS += ibus fcitx
}
contains(QT_CONFIG, xcb-plugin): SUBDIRS += compose
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index caa8884..b083e65 100644
@ -11213,7 +11230,7 @@ index caa8884..b083e65 100644
+ // Don't terminate if reflectionDelegate does not respond to that selector, just use the default.
+ //return NSTerminateNow;
}
if ([self canQuit]) {
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 5a199de..5622728 100644
@ -11227,7 +11244,7 @@ index 5a199de..5622728 100644
+ // Optimize redraw - don't clear image if it will be fully redrawn.
+ bool m_qImageNeedsClear;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index ca92103..225d85f 100644
@ -11235,14 +11252,14 @@ index ca92103..225d85f 100644
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -38,7 +38,8 @@
QT_BEGIN_NAMESPACE
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
+ // Optimize redraw - don't clear image if it will be fully redrawn.
+ : QPlatformBackingStore(window), m_qImageNeedsClear(false)
{
}
@@ -59,9 +60,11 @@ QPaintDevice *QCocoaBackingStore::paintDevice()
if (m_qImage.size() != effectiveBufferSize) {
QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient)
@ -11257,7 +11274,7 @@ index ca92103..225d85f 100644
}
return &m_qImage;
@@ -100,7 +103,8 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
void QCocoaBackingStore::beginPaint(const QRegion &region)
{
- if (m_qImage.hasAlphaChannel()) {
@ -11282,7 +11299,7 @@ index c2d206f..0f9b512 100644
+
return true;
}
@@ -466,7 +472,8 @@ QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const
Qt::KeyboardModifiers neededMods = ModsTbl[i];
int key = kbItem->qtKey[i];
@ -11316,7 +11333,7 @@ index 8152c57..a7c1ca0 100644
+ const int padding = 0;
const int menuHeight = [[NSStatusBar systemStatusBar] thickness];
const int maxImageHeight = menuHeight - padding;
@@ -207,8 +211,11 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// devicePixelRatio for the "best" screen on the system.
qreal devicePixelRatio = qApp->devicePixelRatio();
@ -11331,21 +11348,21 @@ index 8152c57..a7c1ca0 100644
// with a height smaller or equal to maxPixmapHeight. The pixmap
// may rectangular; assume it has a reasonable size. If there is
@@ -224,9 +231,9 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
// Handle SVG icons, which do not return anything for availableSizes().
if (!selectedSize.isValid())
- selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight));
+ selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight), mode);
- QPixmap pixmap = icon.pixmap(selectedSize);
+ QPixmap pixmap = icon.pixmap(selectedSize, mode);
// Draw a low-resolution icon if there is not enough pixels for a retina
// icon. This prevents showing a small icon on retina displays.
@@ -374,6 +381,11 @@ QT_END_NAMESPACE
Q_UNUSED(notification);
down = NO;
+ // Create a rich os x tray icon (pixel-perfect, theme switching).
+ parent->iconSelected = false;
+ parent->systray->updateIcon(parent->icon);
@ -11353,11 +11370,11 @@ index 8152c57..a7c1ca0 100644
+
[self setNeedsDisplay:YES];
}
@@ -383,6 +395,10 @@ QT_END_NAMESPACE
int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
+ // Create a rich os x tray icon (pixel-perfect, theme switching).
+ parent->iconSelected = (clickCount != 2) && parent->menu;
+ parent->systray->updateIcon(parent->icon);
@ -11376,7 +11393,7 @@ index 8152c57..a7c1ca0 100644
+
[self menuTrackingDone:nil];
}
@@ -410,6 +431,11 @@ QT_END_NAMESPACE
-(void)rightMouseUp:(NSEvent *)mouseEvent
{
@ -11388,10 +11405,10 @@ index 8152c57..a7c1ca0 100644
+
[self menuTrackingDone:nil];
}
@@ -425,7 +451,8 @@ QT_END_NAMESPACE
}
-(void)drawRect:(NSRect)rect {
- [[parent item] drawStatusBarBackgroundInRect:rect withHighlight:down];
+ // Create a rich os x tray icon (pixel-perfect, theme switching).
@ -11428,7 +11445,7 @@ index 00cb43c..4530862 100644
@@ -141,7 +141,8 @@ static bool isMouseEvent(NSEvent *ev)
if (!self.window.delegate)
return; // Already detached, pending NSAppKitDefined event
- if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
+ // Fix restore after minimize or close by window buttons.
+ if (pw && pw->frameStrutEventsEnabled() && pw->m_synchedWindowState != Qt::WindowMinimized && pw->m_isExposed && isMouseEvent(theEvent)) {
@ -11438,7 +11455,7 @@ index 00cb43c..4530862 100644
@@ -931,6 +932,15 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
[m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""];
}
+// Create a good os x window icon (pixel-perfect).
+qreal _win_devicePixelRatio() {
+ qreal result = 1.0;
@ -11478,7 +11495,7 @@ index 0d80333..729d4d0 100644
}
@@ -1451,14 +1452,14 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
quint32 nativeVirtualKey = [nsevent keyCode];
QChar ch = QChar::ReplacementCharacter;
- int keyCode = Qt::Key_unknown;
- if ([characters length] != 0) {
@ -11496,13 +11513,13 @@ index 0d80333..729d4d0 100644
+ ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+
+ int keyCode = [self convertKeyCode:ch];
// we will send a key event unless the input method sets m_sendKeyEvent to false
m_sendKeyEvent = true;
@@ -1524,6 +1525,23 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
[self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)];
}
+// Enable Ctrl+Tab and Ctrl+Shift+Tab / Ctrl+Backtab handle in-app.
+- (BOOL)performKeyEquivalent:(NSEvent *)nsevent
+{
@ -11530,7 +11547,7 @@ index 9211fd1..283aabd 100644
@@ -716,12 +716,20 @@ public:
void setSelectedFiles(const QList<QUrl> &);
QString selectedFile() const;
+ // Adding select-by-url for Windows file dialog.
+ void setSelectedRemoteContent(const QByteArray &);
+ QByteArray selectedRemoteContent() const;
@ -11551,7 +11568,7 @@ index 9211fd1..283aabd 100644
@@ -775,6 +783,21 @@ inline void QWindowsFileDialogSharedData::setSelectedFiles(const QList<QUrl> &ur
m_data->selectedFiles = urls;
}
+// Adding select-by-url for Windows file dialog.
+inline QByteArray QWindowsFileDialogSharedData::selectedRemoteContent() const
+{
@ -11573,7 +11590,7 @@ index 9211fd1..283aabd 100644
@@ -899,6 +922,9 @@ public:
// example by appended default suffixes, etc.
virtual QList<QUrl> dialogResult() const = 0;
+ // Adding select-by-url for Windows file dialog.
+ virtual QByteArray dialogRemoteContent() const { return QByteArray(); }
+
@ -11595,7 +11612,7 @@ index 9211fd1..283aabd 100644
+ m_fileDialog->SetFileName((wchar_t*)file.utf16());;
+ }
}
// Return the index of the selected filter, accounting for QFileDialog
@@ -1405,7 +1438,11 @@ bool QWindowsNativeFileDialogBase::onFileOk()
{
@ -11608,12 +11625,12 @@ index 9211fd1..283aabd 100644
+
+ return true;
}
void QWindowsNativeFileDialogBase::close()
@@ -1534,6 +1571,9 @@ public:
QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
QList<QUrl> dialogResult() const Q_DECL_OVERRIDE;
+ // Adding select-by-url for Windows file dialog.
+ QByteArray dialogRemoteContent() const Q_DECL_OVERRIDE;
+
@ -11623,7 +11640,7 @@ index 9211fd1..283aabd 100644
@@ -1548,6 +1588,62 @@ QList<QUrl> QWindowsNativeOpenFileDialog::dialogResult() const
return result;
}
+// Adding select-by-url for Windows file dialog.
+QByteArray QWindowsNativeOpenFileDialog::dialogRemoteContent() const
+{
@ -11697,7 +11714,7 @@ index 9211fd1..283aabd 100644
@@ -1704,6 +1804,12 @@ QList<QUrl> QWindowsFileDialogHelper::selectedFiles() const
return m_data.selectedFiles();
}
+// Adding select-by-url for Windows file dialog.
+QByteArray QWindowsFileDialogHelper::selectedRemoteContent() const
+{
@ -11721,7 +11738,7 @@ index 9211fd1..283aabd 100644
@@ -2036,6 +2146,12 @@ QList<QUrl> QWindowsXpFileDialogHelper::selectedFiles() const
return m_data.selectedFiles();
}
+// Adding select-by-url for Windows file dialog.
+QByteArray QWindowsXpFileDialogHelper::selectedRemoteContent() const
+{
@ -11747,7 +11764,7 @@ index cc697ba..c72234f 100644
// but that cannot handle a Windows command line [yet].
command.replace(QStringLiteral("%1"), url.toString(QUrl::FullyEncoded));
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 7f45b48..4ace49c 100644
index 7f45b48..9d5c339 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1025,7 +1025,8 @@ void QWindowsWindow::destroyWindow()
@ -11782,6 +11799,24 @@ index 7f45b48..4ace49c 100644
if (newTransientParent != oldTransientParent)
SetWindowLongPtr(m_data.hwnd, GWL_HWNDPARENT, (LONG_PTR)newTransientParent);
#endif // !Q_OS_WINCE
@@ -1453,10 +1469,14 @@ void QWindowsWindow::handleResized(int wParam)
handleGeometryChange();
break;
case SIZE_RESTORED:
- if (isFullScreen_sys())
- handleWindowStateChange(Qt::WindowFullScreen);
- else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
+ if (isFullScreen_sys()) {
+ if (m_windowState != Qt::WindowFullScreen)
+ // When resolution is changed for a frameless fullscreen widget
+ // this call prevents correct geometry get in handleGeometryChange().
+ handleWindowStateChange(Qt::WindowFullScreen);
+ } else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen)) {
handleWindowStateChange(Qt::WindowNoState);
+ }
handleGeometryChange();
break;
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 6fffa1e..288df03 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
@ -11804,7 +11839,7 @@ index 3f3a6e7..f1cf176 100644
@@ -1200,6 +1200,15 @@ QList<QUrl> QFileDialogPrivate::userSelectedFiles() const
return files;
}
+// Adding select-by-url for Windows file dialog.
+QByteArray QFileDialogPrivate::userSelectedRemoteContent() const
+{
@ -11820,7 +11855,7 @@ index 3f3a6e7..f1cf176 100644
@@ -1267,6 +1276,14 @@ QStringList QFileDialog::selectedFiles() const
return files;
}
+// Adding select-by-url for Windows file dialog.
+QByteArray QFileDialog::selectedRemoteContent() const
+{
@ -11839,13 +11874,13 @@ index ffe49a2..4213206 100644
@@ -108,6 +108,9 @@ public:
void selectFile(const QString &filename);
QStringList selectedFiles() const;
+ // Adding select-by-url for Windows file dialog.
+ QByteArray selectedRemoteContent() const;
+
void selectUrl(const QUrl &url);
QList<QUrl> selectedUrls() const;
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index f610e46..ca71d55 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
@ -11875,7 +11910,7 @@ index f610e46..ca71d55 100644
@@ -393,6 +401,14 @@ inline QList<QUrl> QFileDialogPrivate::selectedFiles_sys() const
return QList<QUrl>();
}
+// Adding select-by-url for Windows file dialog.
+inline QByteArray QFileDialogPrivate::selectedRemoteContent_sys() const
+{
@ -11914,7 +11949,35 @@ index ebb2921..8119bad 100644
+ qpa_sys->updateMenu(nullptr);
}
}
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 65d06ea..920f529 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -640,15 +640,19 @@ scrolling range.
QSize QAbstractScrollArea::maximumViewportSize() const
{
Q_D(const QAbstractScrollArea);
- int hsbExt = d->hbar->sizeHint().height();
- int vsbExt = d->vbar->sizeHint().width();
int f = 2 * d->frameWidth;
QSize max = size() - QSize(f + d->left + d->right, f + d->top + d->bottom);
- if (d->vbarpolicy == Qt::ScrollBarAlwaysOn)
+ if (d->vbarpolicy == Qt::ScrollBarAlwaysOn) {
+ // Count the sizeHint of the bar only if it is displayed.
+ int vsbExt = d->vbar->sizeHint().width();
max.rwidth() -= vsbExt;
- if (d->hbarpolicy == Qt::ScrollBarAlwaysOn)
+ }
+ if (d->hbarpolicy == Qt::ScrollBarAlwaysOn) {
+ // Count the sizeHint of the bar only if it is displayed.
+ int hsbExt = d->hbar->sizeHint().height();
max.rheight() -= hsbExt;
+ }
return max;
}
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 436937b..fc7a843 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
@ -11933,7 +11996,7 @@ index 436937b..fc7a843 100644
#endif
@@ -1881,11 +1886,21 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
}
// QTBUG-35734: ignore Ctrl/Ctrl+Shift; accept only AltGr (Alt+Ctrl) on German keyboards
- if (unknown && !isReadOnly()
- && event->modifiers() != Qt::ControlModifier

View File

@ -2157,17 +2157,6 @@ btnContext: iconedButton(btnDefIconed) {
downTextPos: point(16px, 8px);
}
photoLoader: size(52px, 22px);
photoLoaderBg: #00000054;
photoLoaderCnt: 3;
photoLoaderPoint: size(6px, 6px);
photoLoaderSkip: 6px;
photoLoaderPeriod: 600; // ms full period
photoLoaderDelta: 150; // ms between points
photoLoaderDuration1: 150; // ms fade in
photoLoaderDuration2: 150; // ms fade out
photoLoaderAlphaMin: 0.1; // not less than that
radialSize: size(50px, 50px);
radialLine: 3px;
radialDuration: 350;
@ -2178,10 +2167,6 @@ radialDownloadOpacity: 0.8;
radialCancel: sprite(378px, 50px, 18px, 18px);
radialCancelOpacity: 1.0;
mediaviewLoader: size(78px, 33px);
mediaviewLoaderPoint: size(9px, 9px);
mediaviewLoaderSkip: 9px;
downloadPathSkip: 10px;
usernamePadding: margins(23px, 22px, 21px, 12px);

View File

@ -697,7 +697,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_in_dlg_audio" = "Voice message";
"lng_in_dlg_file" = "File";
"lng_in_dlg_sticker" = "Sticker";
"lng_in_dlg_sticker_emoji" = "{emoji} (sticker)";
"lng_in_dlg_sticker_emoji" = "{emoji} Sticker";
"lng_ban_user" = "Ban User";
"lng_delete_all_from" = "Delete all from this user";
@ -726,7 +726,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_wont_be_notified" = "Members will not be notified when you post";
"lng_empty_history" = "";
"lng_willbe_history" = "Please select a chat to start messaging";
"lng_message_with_from" = "[c]{from}:[/c] {message}";
"lng_from_you" = "You";
"lng_from_draft" = "Draft";
"lng_bot_description" = "What can this bot do?";
@ -735,6 +734,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_channel_mute" = "Mute";
"lng_channel_unmute" = "Unmute";
"lng_dialogs_text_with_from" = "{from_part} {message}";
"lng_dialogs_text_from_wrapped" = "{from}:";
"lng_dialogs_text_media" = "{media_part} {caption}";
"lng_dialogs_text_media_wrapped" = "{media},";
"lng_open_this_link" = "Open this link?";
"lng_open_link" = "Open";
@ -880,7 +884,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_selected_upload_stop" = "Stop";
"lng_selected_delete_sure_this" = "Do you want to delete this message?";
"lng_selected_delete_sure" = "Do you want to delete {count:_not_used_|# message|# messages}?";
//"lng_delete_photo_sure" = "Do you want to delete this photo?";
"lng_delete_photo_sure" = "Do you want to delete this photo?";
"lng_box_delete" = "Delete";
"lng_box_leave" = "Leave";

View File

@ -88,10 +88,9 @@ void paintRow(Painter &p, History *history, HistoryItem *item, Data::Draft *draf
p.setPen(active ? st::dialogsTextFgActive : st::dialogsTextFgService);
if (history->typing.isEmpty() && history->sendActions.isEmpty()) {
if (history->cloudDraftTextCache.isEmpty()) {
TextCustomTagsMap custom;
custom.insert(QChar('c'), qMakePair(textcmdStartLink(1), textcmdStopLink()));
QString msg = lng_message_with_from(lt_from, textRichPrepare(lang(lng_from_draft)), lt_message, textRichPrepare(draft->textWithTags.text));
history->cloudDraftTextCache.setRichText(st::dialogsTextFont, msg, _textDlgOptions, custom);
auto draftWrapped = textcmdLink(1, lng_dialogs_text_from_wrapped(lt_from, lang(lng_from_draft)));
auto draftText = lng_dialogs_text_with_from(lt_from_part, draftWrapped, lt_message, textClean(draft->textWithTags.text));
history->cloudDraftTextCache.setText(st::dialogsTextFont, draftText, _textDlgOptions);
}
textstyleSet(&(active ? st::dialogsTextStyleActive : st::dialogsTextStyleDraft));
p.setFont(st::dialogsTextFont);

View File

@ -2959,6 +2959,49 @@ void HistoryItem::recountDisplayDate() {
}
}
QString HistoryItem::notificationText() const {
auto getText = [this]() {
if (emptyText()) {
return _media ? _media->notificationText() : QString();
}
return _text.originalText();
};
auto result = getText();
if (result.size() > 0xFF) result = result.mid(0, 0xFF) + qsl("...");
return result;
}
QString HistoryItem::inDialogsText() const {
auto getText = [this]() {
if (emptyText()) {
return _media ? _media->inDialogsText() : QString();
}
return textClean(_text.originalText());
};
auto plainText = getText();
if ((!_history->peer->isUser() || out()) && !isPost() && !isEmpty()) {
auto fromText = author()->isSelf() ? lang(lng_from_you) : author()->shortName();
auto fromWrapped = textcmdLink(1, lng_dialogs_text_from_wrapped(lt_from, textClean(fromText)));
return lng_dialogs_text_with_from(lt_from_part, fromWrapped, lt_message, plainText);
}
return plainText;
}
void HistoryItem::drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const {
if (cacheFor != this) {
cacheFor = this;
cache.setText(st::dialogsTextFont, inDialogsText(), _textDlgOptions);
}
if (r.width()) {
textstyleSet(&(act ? st::dialogsTextStyleActive : st::dialogsTextStyle));
p.setFont(st::dialogsTextFont);
p.setPen(act ? st::dialogsTextFgActive : st::dialogsTextFg);
cache.drawElided(p, r.left(), r.top(), r.width(), r.height() / st::dialogsTextFont->height);
textstyleRestore();
}
}
HistoryItem::~HistoryItem() {
App::historyUnregItem(this);
if (id < 0 && App::uploader()) {
@ -3041,6 +3084,11 @@ void RadialAnimation::draw(Painter &p, const QRect &inner, int32 thickness, cons
p.setOpacity(o);
}
QString HistoryMedia::inDialogsText() const {
auto result = notificationText();
return result.isEmpty() ? QString() : textcmdLink(1, textClean(result));
}
namespace {
int32 documentMaxStatusWidth(DocumentData *document) {
@ -3083,6 +3131,26 @@ TextWithEntities captionedSelectedText(const QString &attachType, const Text &ca
return result;
}
QString captionedNotificationText(const QString &attachType, const Text &caption) {
if (caption.isEmpty()) {
return attachType;
}
auto captionText = caption.originalText();
auto attachTypeWrapped = lng_dialogs_text_media_wrapped(lt_media, attachType);
return lng_dialogs_text_media(lt_media_part, attachTypeWrapped, lt_caption, captionText);
}
QString captionedInDialogsText(const QString &attachType, const Text &caption) {
if (caption.isEmpty()) {
return textcmdLink(1, textClean(attachType));
}
auto captionText = textClean(caption.originalText());
auto attachTypeWrapped = textcmdLink(1, lng_dialogs_text_media_wrapped(lt_media, textClean(attachType)));
return lng_dialogs_text_media(lt_media_part, attachTypeWrapped, lt_caption, captionText);
}
} // namespace
void HistoryFileMedia::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
@ -3501,8 +3569,12 @@ void HistoryPhoto::detachFromParent() {
App::unregPhotoItem(_data, _parent);
}
QString HistoryPhoto::notificationText() const {
return captionedNotificationText(lang(lng_in_dlg_photo), _caption);
}
QString HistoryPhoto::inDialogsText() const {
return _caption.isEmpty() ? lang(lng_in_dlg_photo) : _caption.originalText(AllTextSelection, ExpandLinksNone);
return captionedInDialogsText(lang(lng_in_dlg_photo), _caption);
}
TextWithEntities HistoryPhoto::selectedText(TextSelection selection) const {
@ -3747,8 +3819,12 @@ void HistoryVideo::setStatusSize(int32 newSize) const {
HistoryFileMedia::setStatusSize(newSize, _data->size, _data->duration(), 0);
}
QString HistoryVideo::notificationText() const {
return captionedNotificationText(lang(lng_in_dlg_video), _caption);
}
QString HistoryVideo::inDialogsText() const {
return _caption.isEmpty() ? lang(lng_in_dlg_video) : _caption.originalText(AllTextSelection, ExpandLinksNone);
return captionedInDialogsText(lang(lng_in_dlg_video), _caption);
}
TextWithEntities HistoryVideo::selectedText(TextSelection selection) const {
@ -4224,28 +4300,36 @@ HistoryTextState HistoryDocument::getState(int x, int y, HistoryStateRequest req
return result;
}
QString HistoryDocument::notificationText() const {
QString result;
buildStringRepresentation([&result](const QString &type, const QString &fileName, const Text &caption) {
result = captionedNotificationText(fileName.isEmpty() ? type : fileName, caption);
});
return result;
}
QString HistoryDocument::inDialogsText() const {
QString result;
if (Has<HistoryDocumentVoice>()) {
result = lang(lng_in_dlg_audio);
} else if (auto song = _data->song()) {
result = documentName(_data);
if (result.isEmpty()) {
result = lang(lng_in_dlg_audio_file);
}
} else {
auto named = Get<HistoryDocumentNamed>();
result = (!named || named->_name.isEmpty()) ? lang(lng_in_dlg_file) : named->_name;
}
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
if (!captioned->_caption.isEmpty()) {
result.append(' ').append(captioned->_caption.originalText(AllTextSelection, ExpandLinksNone));
}
}
buildStringRepresentation([&result](const QString &type, const QString &fileName, const Text &caption) {
result = captionedInDialogsText(fileName.isEmpty() ? type : fileName, caption);
});
return result;
}
TextWithEntities HistoryDocument::selectedText(TextSelection selection) const {
TextWithEntities result;
buildStringRepresentation([&result, selection](const QString &type, const QString &fileName, const Text &caption) {
auto fullType = type;
if (!fileName.isEmpty()) {
fullType.append(qstr(" : ")).append(fileName);
}
result = captionedSelectedText(fullType, caption, selection);
});
return result;
}
template <typename Callback>
void HistoryDocument::buildStringRepresentation(Callback callback) const {
const Text emptyCaption;
const Text *caption = &emptyCaption;
if (auto captioned = Get<HistoryDocumentCaptioned>()) {
@ -4257,12 +4341,14 @@ TextWithEntities HistoryDocument::selectedText(TextSelection selection) const {
} else if (_data->song()) {
attachType = lang(lng_in_dlg_audio_file);
}
QString attachFileName;
if (auto named = Get<HistoryDocumentNamed>()) {
if (!named->_name.isEmpty()) {
attachType.append(qstr(" : ")).append(named->_name);
attachFileName = named->_name;
}
}
return captionedSelectedText(attachType, *caption, selection);
return callback(attachType, attachFileName, *caption);
}
void HistoryDocument::setStatusSize(int32 newSize, qint64 realDuration) const {
@ -4696,8 +4782,12 @@ HistoryTextState HistoryGif::getState(int x, int y, HistoryStateRequest request)
return result;
}
QString HistoryGif::notificationText() const {
return captionedNotificationText(qsl("GIF"), _caption);
}
QString HistoryGif::inDialogsText() const {
return qsl("GIF") + (_caption.isEmpty() ? QString() : (' ' + _caption.originalText(AllTextSelection, ExpandLinksNone)));
return captionedInDialogsText(qsl("GIF"), _caption);
}
TextWithEntities HistoryGif::selectedText(TextSelection selection) const {
@ -5014,15 +5104,19 @@ HistoryTextState HistorySticker::getState(int x, int y, HistoryStateRequest requ
return result;
}
QString HistorySticker::inDialogsText() const {
QString HistorySticker::toString() const {
return _emoji.isEmpty() ? lang(lng_in_dlg_sticker) : lng_in_dlg_sticker_emoji(lt_emoji, _emoji);
}
QString HistorySticker::notificationText() const {
return toString();
}
TextWithEntities HistorySticker::selectedText(TextSelection selection) const {
if (selection != FullSelection) {
return TextWithEntities();
}
return { qsl("[ ") + inDialogsText() + qsl(" ]"), EntitiesInText() };
return { qsl("[ ") + toString() + qsl(" ]"), EntitiesInText() };
}
void HistorySticker::attachToParent() {
@ -5202,7 +5296,7 @@ HistoryTextState HistoryContact::getState(int x, int y, HistoryStateRequest requ
return result;
}
QString HistoryContact::inDialogsText() const {
QString HistoryContact::notificationText() const {
return lang(lng_in_dlg_contact);
}
@ -5723,10 +5817,6 @@ void HistoryWebPage::detachFromParent() {
if (_attach) _attach->detachFromParent();
}
QString HistoryWebPage::inDialogsText() const {
return QString();
}
TextWithEntities HistoryWebPage::selectedText(TextSelection selection) const {
if (selection == FullSelection) {
return TextWithEntities();
@ -6172,8 +6262,12 @@ TextSelection HistoryLocation::adjustSelection(TextSelection selection, TextSele
return { titleSelection.from, fromDescriptionSelection(descriptionSelection).to };
}
QString HistoryLocation::notificationText() const {
return captionedNotificationText(lang(lng_maps_point), _title);
}
QString HistoryLocation::inDialogsText() const {
return _title.isEmpty() ? lang(lng_maps_point) : _title.originalText(AllTextSelection);
return captionedInDialogsText(lang(lng_maps_point), _title);
}
TextWithEntities HistoryLocation::selectedText(TextSelection selection) const {
@ -6301,7 +6395,7 @@ bool HistoryMessageReply::updateData(HistoryMessage *holder, bool force) {
}
if (replyToMsg) {
replyToText.setText(st::msgFont, replyToMsg->inReplyText(), _textDlgOptions);
replyToText.setText(st::msgFont, textClean(replyToMsg->inReplyText()), _textDlgOptions);
updateName();
@ -7032,10 +7126,6 @@ TextWithEntities HistoryMessage::selectedText(TextSelection selection) const {
return result;
}
QString HistoryMessage::inDialogsText() const {
return emptyText() ? (_media ? _media->inDialogsText() : QString()) : _text.originalText(AllTextSelection, ExpandLinksNone);
}
void HistoryMessage::setMedia(const MTPMessageMedia *media) {
if (!_media && (!media || media->type() == mtpc_messageMediaEmpty)) return;
@ -7698,38 +7788,10 @@ TextSelection HistoryMessage::adjustSelection(TextSelection selection, TextSelec
return { textSelection.from, fromMediaSelection(mediaSelection).to };
}
void HistoryMessage::drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const {
if (cacheFor != this) {
cacheFor = this;
QString msg(inDialogsText());
if ((!_history->peer->isUser() || out()) && !isPost() && !isEmpty()) {
TextCustomTagsMap custom;
custom.insert(QChar('c'), qMakePair(textcmdStartLink(1), textcmdStopLink()));
msg = lng_message_with_from(lt_from, textRichPrepare((author() == App::self()) ? lang(lng_from_you) : author()->shortName()), lt_message, textRichPrepare(msg));
cache.setRichText(st::dialogsTextFont, msg, _textDlgOptions, custom);
} else {
cache.setText(st::dialogsTextFont, msg, _textDlgOptions);
}
}
if (r.width()) {
textstyleSet(&(act ? st::dialogsTextStyleActive : st::dialogsTextStyle));
p.setFont(st::dialogsTextFont);
p.setPen(act ? st::dialogsTextFgActive : (emptyText() ? st::dialogsTextFgService : st::dialogsTextFg));
cache.drawElided(p, r.left(), r.top(), r.width(), r.height() / st::dialogsTextFont->height);
textstyleRestore();
}
}
QString HistoryMessage::notificationHeader() const {
return (!_history->peer->isUser() && !isPost()) ? from()->name : QString();
}
QString HistoryMessage::notificationText() const {
QString msg(inDialogsText());
if (msg.size() > 0xFF) msg = msg.mid(0, 0xFF) + qsl("...");
return msg;
}
bool HistoryMessage::displayFromPhoto() const {
return hasFromPhoto() && !isAttachedToPrevious();
}
@ -8043,11 +8105,11 @@ TextWithEntities HistoryService::selectedText(TextSelection selection) const {
}
QString HistoryService::inDialogsText() const {
return _text.originalText(AllTextSelection, ExpandLinksNone);
return textcmdLink(1, textClean(notificationText()));
}
QString HistoryService::inReplyText() const {
QString result = HistoryService::inDialogsText();
QString result = HistoryService::notificationText();
return result.trimmed().startsWith(author()->name) ? result.trimmed().mid(author()->name.size()).trimmed() : result;
}
@ -8184,22 +8246,6 @@ HistoryTextState HistoryService::getState(int x, int y, HistoryStateRequest requ
return result;
}
void HistoryService::drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const {
if (cacheFor != this) {
cacheFor = this;
cache.setText(st::dialogsTextFont, inDialogsText(), _textDlgOptions);
}
QRect tr(r);
p.setPen(act ? st::dialogsTextFgActive : st::dialogsTextFgService);
cache.drawElided(p, tr.left(), tr.top(), tr.width(), tr.height() / st::dialogsTextFont->height);
}
QString HistoryService::notificationText() const {
QString msg = _text.originalText();
if (msg.size() > 0xFF) msg = msg.mid(0, 0xFF) + qsl("...");
return msg;
}
void HistoryService::applyEditionToEmpty() {
TextWithEntities textWithEntities = { QString(), EntitiesInText() };
setServiceText(QString());

View File

@ -1212,11 +1212,17 @@ public:
virtual TextWithEntities selectedText(TextSelection selection) const {
return { qsl("[-]"), EntitiesInText() };
}
virtual QString inDialogsText() const {
return qsl("-");
virtual QString notificationHeader() const {
return QString();
}
virtual QString notificationText() const;
// Returns text with link-start and link-end commands for service-color highlighting.
// Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text"
virtual QString inDialogsText() const;
virtual QString inReplyText() const {
return inDialogsText();
return notificationText();
}
virtual TextWithEntities originalText() const {
return { QString(), EntitiesInText() };
@ -1227,11 +1233,11 @@ public:
virtual void setViewsCount(int32 count) {
}
virtual void setId(MsgId newId);
virtual void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const = 0;
virtual QString notificationHeader() const {
return QString();
}
virtual QString notificationText() const = 0;
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const;
bool emptyText() const {
return _text.isEmpty();
}
bool canDelete() const {
ChannelData *channel = _history->peer->asChannel();
@ -1593,7 +1599,14 @@ public:
HistoryMedia &operator=(const HistoryMedia &other) = delete;
virtual HistoryMediaType type() const = 0;
virtual QString inDialogsText() const = 0;
virtual QString notificationText() const {
return QString();
}
// Returns text with link-start and link-end commands for service-color highlighting.
// Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text"
virtual QString inDialogsText() const;
virtual TextWithEntities selectedText(TextSelection selection) const = 0;
bool hasPoint(int x, int y) const {
@ -1817,6 +1830,7 @@ public:
return !_caption.isEmpty();
}
QString notificationText() const override;
QString inDialogsText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
@ -1897,6 +1911,7 @@ public:
return !_caption.isEmpty();
}
QString notificationText() const override;
QString inDialogsText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
@ -2020,6 +2035,7 @@ public:
return Has<HistoryDocumentCaptioned>();
}
QString notificationText() const override;
QString inDialogsText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
@ -2076,11 +2092,17 @@ protected:
private:
void createComponents(bool caption);
DocumentData *_data;
void setStatusSize(int32 newSize, qint64 realDuration = 0) const;
bool updateStatusText() const; // returns showPause
// Callback is a void(const QString &, const QString &, const Text &) functor.
// It will be called as callback(attachType, attachFileName, attachCaption).
template <typename Callback>
void buildStringRepresentation(Callback callback) const;
DocumentData *_data;
};
class HistoryGif : public HistoryFileMedia {
@ -2107,6 +2129,7 @@ public:
return !_caption.isEmpty();
}
QString notificationText() const override;
QString inDialogsText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
@ -2205,7 +2228,7 @@ public:
return true;
}
QString inDialogsText() const override;
QString notificationText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
DocumentData *getDocument() override {
@ -2230,6 +2253,7 @@ private:
int additionalWidth() const {
return additionalWidth(_parent->Get<HistoryMessageVia>(), _parent->Get<HistoryMessageReply>());
}
QString toString() const;
int16 _pixw, _pixh;
ClickHandlerPtr _packLink;
@ -2274,7 +2298,7 @@ public:
return true;
}
QString inDialogsText() const override;
QString notificationText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
void attachToParent() override;
@ -2342,7 +2366,6 @@ public:
return _attach && _attach->dragItemByHandler(p);
}
QString inDialogsText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
@ -2476,6 +2499,7 @@ public:
return p == _link;
}
QString notificationText() const override;
QString inDialogsText() const override;
TextWithEntities selectedText(TextSelection selection) const override;
@ -2549,9 +2573,6 @@ public:
int32 plainMaxWidth() const;
void countPositionAndSize(int32 &left, int32 &width) const;
bool emptyText() const {
return _text.isEmpty();
}
bool drawBubble() const {
return _media ? (!emptyText() || _media->needsBubble()) : !isEmpty();
}
@ -2593,9 +2614,7 @@ public:
HistoryItem::clickHandlerPressedChanged(p, pressed);
}
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const override;
QString notificationHeader() const override;
QString notificationText() const override;
void applyEdition(const MTPDmessage &message) override;
void applyEditionToEmpty() override;
@ -2604,7 +2623,6 @@ public:
void eraseFromOverview() override;
TextWithEntities selectedText(TextSelection selection) const override;
QString inDialogsText() const override;
void setText(const TextWithEntities &textWithEntities) override;
TextWithEntities originalText() const override;
bool textHasLinks() const override;
@ -2795,9 +2813,6 @@ public:
HistoryItem::clickHandlerPressedChanged(p, pressed);
}
void drawInDialog(Painter &p, const QRect &r, bool act, const HistoryItem *&cacheFor, Text &cache) const override;
QString notificationText() const override;
void applyEditionToEmpty() override;
int32 addToOverview(AddToOverviewMethod method) override;

View File

@ -5908,7 +5908,7 @@ void HistoryWidget::onKbToggle(bool manual) {
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0;
if (_kbReplyTo && !_editMsgId && !_replyToId && fieldEnabled) {
updateReplyToName();
_replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
_replyEditMsgText.setText(st::msgFont, textClean(_kbReplyTo->inReplyText()), _textDlgOptions);
_fieldBarCancel.show();
updateMouseTracking();
}
@ -5927,7 +5927,7 @@ void HistoryWidget::onKbToggle(bool manual) {
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0;
if (_kbReplyTo && !_editMsgId && !_replyToId) {
updateReplyToName();
_replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
_replyEditMsgText.setText(st::msgFont, textClean(_kbReplyTo->inReplyText()), _textDlgOptions);
_fieldBarCancel.show();
updateMouseTracking();
}
@ -7048,7 +7048,7 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) {
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard.forceReply()) ? App::histItemById(_keyboard.forMsgId()) : 0;
if (_kbReplyTo && !_replyToId) {
updateReplyToName();
_replyEditMsgText.setText(st::msgFont, _kbReplyTo->inDialogsText(), _textDlgOptions);
_replyEditMsgText.setText(st::msgFont, textClean(_kbReplyTo->inReplyText()), _textDlgOptions);
_fieldBarCancel.show();
updateMouseTracking();
}
@ -7285,7 +7285,7 @@ void HistoryWidget::updatePinnedBar(bool force) {
_pinnedBar->msg = App::histItemById(_history->channelId(), _pinnedBar->msgId);
}
if (_pinnedBar->msg) {
_pinnedBar->text.setText(st::msgFont, _pinnedBar->msg->inDialogsText(), _textDlgOptions);
_pinnedBar->text.setText(st::msgFont, textClean(_pinnedBar->msg->notificationText()), _textDlgOptions);
update();
} else if (force) {
if (_peer && _peer->isMegagroup()) {
@ -7523,7 +7523,7 @@ void HistoryWidget::onReplyToMessage() {
} else {
_replyEditMsg = to;
_replyToId = to->id;
_replyEditMsgText.setText(st::msgFont, _replyEditMsg->inDialogsText(), _textDlgOptions);
_replyEditMsgText.setText(st::msgFont, textClean(_replyEditMsg->inReplyText()), _textDlgOptions);
updateBotKeyboard();
@ -7869,7 +7869,7 @@ void HistoryWidget::updatePreview() {
updateMouseTracking();
if (_previewData->pendingTill) {
_previewTitle.setText(st::msgServiceNameFont, lang(lng_preview_loading), _textNameOptions);
_previewDescription.setText(st::msgFont, _previewLinks.splitRef(' ').at(0).toString(), _textDlgOptions);
_previewDescription.setText(st::msgFont, textClean(_previewLinks.splitRef(' ').at(0).toString()), _textDlgOptions);
int32 t = (_previewData->pendingTill - unixtime()) * 1000;
if (t <= 0) t = 1;
@ -7901,7 +7901,7 @@ void HistoryWidget::updatePreview() {
}
}
_previewTitle.setText(st::msgServiceNameFont, title, _textNameOptions);
_previewDescription.setText(st::msgFont, desc, _textDlgOptions);
_previewDescription.setText(st::msgFont, textClean(desc), _textDlgOptions);
}
} else if (!readyToForward() && !replyToId() && !_editMsgId) {
_fieldBarCancel.hide();
@ -8163,7 +8163,7 @@ void HistoryWidget::updateReplyEditTexts(bool force) {
_replyEditMsg = App::histItemById(_channel, _editMsgId ? _editMsgId : _replyToId);
}
if (_replyEditMsg) {
_replyEditMsgText.setText(st::msgFont, _replyEditMsg->inDialogsText(), _textDlgOptions);
_replyEditMsgText.setText(st::msgFont, textClean(_replyEditMsg->inReplyText()), _textDlgOptions);
updateBotKeyboard();

View File

@ -40,7 +40,7 @@ TextParseOptions _textNameOptions = {
Qt::LayoutDirectionAuto, // lang-dependent
};
TextParseOptions _textDlgOptions = {
0, // flags
TextParseRichText, // flags
0, // maxw is style-dependent
1, // maxh
Qt::LayoutDirectionAuto, // lang-dependent

View File

@ -256,7 +256,7 @@ void MainWidget::updateForwardingTexts() {
}
}
_toForwardFrom.setText(st::msgServiceNameFont, from, _textNameOptions);
_toForwardText.setText(st::msgFont, text, _textDlgOptions);
_toForwardText.setText(st::msgFont, textClean(text), _textDlgOptions);
_toForwardNameVersion = version;
}
@ -632,10 +632,9 @@ void MainWidget::deleteLayer(int32 selectedCount) {
void MainWidget::deletePhotoLayer(PhotoData *photo) {
_deletingPhoto = photo;
onDeletePhotoSure(); // langs are not ready yet
//auto box = new ConfirmBox(lang(lng_delete_photo_sure), lang(lng_box_delete));
//connect(box, SIGNAL(confirmed()), this, SLOT(onDeletePhotoSure()));
//Ui::showLayer(box);
auto box = new ConfirmBox(lang(lng_delete_photo_sure), lang(lng_box_delete));
connect(box, SIGNAL(confirmed()), this, SLOT(onDeletePhotoSure()));
Ui::showLayer(box);
}
void MainWidget::onDeletePhotoSure() {
@ -1843,7 +1842,14 @@ void MainWidget::setChatBackground(const App::WallPaper &wp) {
}
bool MainWidget::chatBackgroundLoading() {
return !!_background;
return (_background != nullptr);
}
float64 MainWidget::chatBackgroundProgress() const {
if (_background) {
return _background->full->progress();
}
return 1.;
}
void MainWidget::checkChatBackground() {

View File

@ -345,6 +345,7 @@ public:
void setChatBackground(const App::WallPaper &wp);
bool chatBackgroundLoading();
float64 chatBackgroundProgress() const;
void checkChatBackground();
ImagePtr newBackgroundThumb();

View File

@ -88,6 +88,8 @@ MediaView::MediaView() : TWidget(App::wnd())
_saveMsg = QRect(0, 0, _saveMsgText.maxWidth() + st::medviewSaveMsgPadding.left() + st::medviewSaveMsgPadding.right(), st::medviewSaveMsgFont->height + st::medviewSaveMsgPadding.top() + st::medviewSaveMsgPadding.bottom());
_saveMsgText.setLink(1, MakeShared<SaveMsgClickHandler>(this));
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(onScreenResized(int)));
_transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush.rect()));
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
@ -98,6 +100,7 @@ MediaView::MediaView() : TWidget(App::wnd())
hide();
createWinId();
setWindowState(Qt::WindowFullScreen);
_saveMsgUpdater.setSingleShot(true);
connect(&_saveMsgUpdater, SIGNAL(timeout()), this, SLOT(updateImage()));
@ -163,7 +166,10 @@ void MediaView::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) {
if (_photo && _overview == OverviewChatPhotos && _history && !_history->peer->isUser()) {
auto lastChatPhoto = computeLastOverviewChatPhoto();
if (_index < 0 && _photo == lastChatPhoto.photo && _photo == _additionalChatPhoto) {
return showPhoto(_photo, lastChatPhoto.item);
auto firstOpened = _firstOpenedPeerPhoto;
showPhoto(_photo, lastChatPhoto.item);
_firstOpenedPeerPhoto = firstOpened;
return;
}
computeAdditionalChatPhoto(_history->peer, lastChatPhoto.photo);
}
@ -484,7 +490,6 @@ void MediaView::step_radial(uint64 ms, bool timer) {
location.accessDisable();
}
}
}
}
@ -543,6 +548,29 @@ void MediaView::onDropdownHiding() {
}
}
void MediaView::onScreenResized(int screen) {
if (isHidden()) return;
bool ignore = false;
auto screens = QApplication::screens();
if (screen >= 0 && screen < screens.size()) {
if (auto screenHandle = windowHandle()->screen()) {
if (screens.at(screen) != screenHandle) {
ignore = true;
}
}
}
if (!ignore) {
moveToScreen();
auto item = (_msgid ? App::histItemById(_msgmigrated ? 0 : _channel, _msgid) : nullptr);
if (_photo) {
displayPhoto(_photo, item);
} else if (_doc) {
displayDocument(_doc, item);
}
}
}
void MediaView::onToMessage() {
if (HistoryItem *item = _msgid ? App::histItemById(_msgmigrated ? 0 : _channel, _msgid) : 0) {
if (App::wnd()) {
@ -735,7 +763,18 @@ void MediaView::onForward() {
void MediaView::onDelete() {
close();
if (!_msgid) {
auto deletingPeerPhoto = [this]() {
if (!_msgid) return true;
if (_photo && _history) {
auto lastPhoto = computeLastOverviewChatPhoto();
if (lastPhoto.photo == _photo && _history->peer->photoId == _photo->id) {
return _firstOpenedPeerPhoto;
}
}
return false;
};
if (deletingPeerPhoto()) {
App::main()->deletePhotoLayer(_photo);
} else if (auto item = App::histItemById(_msgmigrated ? 0 : _channel, _msgid)) {
App::contextItem(item);
@ -784,6 +823,7 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
_migrated = nullptr;
}
_additionalChatPhoto = nullptr;
_firstOpenedPeerPhoto = false;
_peer = 0;
_user = 0;
_saveMsgStarted = 0;
@ -825,6 +865,7 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
_history = _migrated = nullptr;
_additionalChatPhoto = nullptr;
_firstOpenedPeerPhoto = true;
_peer = context;
_user = context->asUser();
_saveMsgStarted = 0;
@ -868,7 +909,9 @@ void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
auto lastChatPhoto = computeLastOverviewChatPhoto();
if (_photo == lastChatPhoto.photo) {
return showPhoto(_photo, lastChatPhoto.item);
showPhoto(_photo, lastChatPhoto.item);
_firstOpenedPeerPhoto = true;
return;
}
computeAdditionalChatPhoto(_history->peer, lastChatPhoto.photo);

View File

@ -85,6 +85,8 @@ public slots:
void onHideControls(bool force = false);
void onDropdownHiding();
void onScreenResized(int screen);
void onToMessage();
void onSaveAs();
void onDownload();
@ -194,6 +196,12 @@ private:
// in the _history->overview[OverviewChatPhotos] (if the item was deleted).
PhotoData *_additionalChatPhoto = nullptr;
// We save the information about the reason of the current mediaview show:
// did we open a peer profile photo or a photo from some message.
// We use it when trying to delete a photo: if we've opened a peer photo,
// then we'll delete group photo instead of the corresponding message.
bool _firstOpenedPeerPhoto = false;
PeerData *_from = nullptr;
Text _fromName;

View File

@ -188,6 +188,7 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
, _tileBackground(this, lang(lng_settings_bg_tile), cTileBackground())
, _adaptiveForWide(this, lang(lng_settings_adaptive_wide), Global::AdaptiveForWide())
, _needBackgroundUpdate(false)
, _radial(animation(this, &SettingsInner::step_radial))
// advanced
, _passcodeEdit(this, lang(cHasPasscode() ? lng_passcode_change : lng_passcode_turn_on))
@ -318,6 +319,10 @@ SettingsInner::SettingsInner(SettingsWidget *parent) : TWidget(parent)
connect(&_tileBackground, SIGNAL(changed()), this, SLOT(onTileBackground()));
connect(&_adaptiveForWide, SIGNAL(changed()), this, SLOT(onAdaptiveForWide()));
if (radialLoading()) {
radialStart();
}
// advanced
connect(&_passcodeEdit, SIGNAL(clicked()), this, SLOT(onPasscode()));
connect(&_passcodeTurnOff, SIGNAL(clicked()), this, SLOT(onPasscodeOff()));
@ -385,18 +390,6 @@ void SettingsInner::peerUpdated(PeerData *data) {
}
void SettingsInner::paintEvent(QPaintEvent *e) {
bool animateBackground = false;
if (App::main() && App::main()->chatBackgroundLoading()) {
App::main()->checkChatBackground();
if (App::main()->chatBackgroundLoading()) {
animateBackground = true;
} else {
updateChatBackground();
}
} else if (_needBackgroundUpdate) {
updateChatBackground();
}
Painter p(this);
p.setClipRect(e->rect());
@ -620,32 +613,35 @@ void SettingsInner::paintEvent(QPaintEvent *e) {
p.drawText(_left + st::setHeaderLeft, top + st::setHeaderTop + st::setHeaderFont->ascent, lang(lng_settings_section_background));
top += st::setHeaderSkip;
if (animateBackground) {
const QPixmap &pix = App::main()->newBackgroundThumb()->pixBlurred(st::setBackgroundSize);
p.drawPixmap(_left, top, st::setBackgroundSize, st::setBackgroundSize, pix, 0, (pix.height() - st::setBackgroundSize) / 2, st::setBackgroundSize, st::setBackgroundSize);
uint64 dt = getms();
int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
int32 x = _left + (st::setBackgroundSize - st::mediaviewLoader.width()) / 2;
int32 y = top + (st::setBackgroundSize - st::mediaviewLoader.height()) / 2;
p.fillRect(x, y, st::mediaviewLoader.width(), st::mediaviewLoader.height(), st::photoLoaderBg->b);
x += (st::mediaviewLoader.width() - cnt * st::mediaviewLoaderPoint.width() - (cnt - 1) * st::mediaviewLoaderSkip) / 2;
y += (st::mediaviewLoader.height() - st::mediaviewLoaderPoint.height()) / 2;
QColor c(st::white->c);
QBrush b(c);
for (int32 i = 0; i < cnt; ++i) {
t -= delta;
while (t < 0) t += period;
float64 alpha = (t >= st::photoLoaderDuration1 + st::photoLoaderDuration2) ? 0 : ((t > st::photoLoaderDuration1 ? ((st::photoLoaderDuration1 + st::photoLoaderDuration2 - t) / st::photoLoaderDuration2) : (t / st::photoLoaderDuration1)));
c.setAlphaF(st::photoLoaderAlphaMin + alpha * (1 - st::photoLoaderAlphaMin));
b.setColor(c);
p.fillRect(x + i * (st::mediaviewLoaderPoint.width() + st::mediaviewLoaderSkip), y, st::mediaviewLoaderPoint.width(), st::mediaviewLoaderPoint.height(), b);
bool radial = false;
float64 radialOpacity = 0;
if (_radial.animating()) {
_radial.step(getms());
radial = _radial.animating();
radialOpacity = _radial.opacity();
}
if (radial) {
auto backThumb = App::main() ? App::main()->newBackgroundThumb() : ImagePtr();
if (backThumb->isNull()) {
p.drawPixmap(_left, top, _background);
} else {
const QPixmap &pix = App::main()->newBackgroundThumb()->pixBlurred(st::setBackgroundSize);
p.drawPixmap(_left, top, st::setBackgroundSize, st::setBackgroundSize, pix, 0, (pix.height() - st::setBackgroundSize) / 2, st::setBackgroundSize, st::setBackgroundSize);
}
QTimer::singleShot(AnimationTimerDelta, this, SLOT(updateBackgroundRect()));
auto outer = radialRect();
QRect inner(QPoint(outer.x() + (outer.width() - st::radialSize.width()) / 2, outer.y() + (outer.height() - st::radialSize.height()) / 2), st::radialSize);
p.setPen(Qt::NoPen);
p.setBrush(st::black);
p.setOpacity(radialOpacity * st::radialBgOpacity);
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.drawEllipse(inner);
p.setRenderHint(QPainter::HighQualityAntialiasing, false);
p.setOpacity(1);
QRect arc(inner.marginsRemoved(QMargins(st::radialLine, st::radialLine, st::radialLine, st::radialLine)));
_radial.draw(p, arc, st::radialLine, st::white);
} else {
p.drawPixmap(_left, top, _background);
}
@ -953,7 +949,7 @@ void SettingsInner::passcodeChanged() {
}
void SettingsInner::updateBackgroundRect() {
update(_left, _tileBackground.y() - st::setLittleSkip - st::setBackgroundSize, st::setBackgroundSize, st::setBackgroundSize);
update(radialRect());
}
void SettingsInner::onFullPeerUpdated(PeerData *peer) {
@ -1657,6 +1653,53 @@ void SettingsInner::onBackFromFile() {
updateChatBackground();
}
float64 SettingsInner::radialProgress() const {
if (auto m = App::main()) {
return m->chatBackgroundProgress();
}
return 1.;
}
bool SettingsInner::radialLoading() const {
if (auto m = App::main()) {
if (m->chatBackgroundLoading()) {
m->checkChatBackground();
if (m->chatBackgroundLoading()) {
return true;
} else {
const_cast<SettingsInner*>(this)->updateChatBackground();
}
}
}
return false;
}
QRect SettingsInner::radialRect() const {
auto left = _left;
auto top = _tileBackground.y() - st::setLittleSkip - st::setBackgroundSize;
return QRect(left, top, st::setBackgroundSize, st::setBackgroundSize);
}
void SettingsInner::radialStart() {
if (radialLoading() && !_radial.animating()) {
_radial.start(radialProgress());
if (auto shift = radialTimeShift()) {
_radial.update(radialProgress(), !radialLoading(), getms() + shift);
}
}
}
uint64 SettingsInner::radialTimeShift() const {
return st::radialDuration;
}
void SettingsInner::step_radial(uint64 ms, bool timer) {
_radial.update(radialProgress(), !radialLoading(), ms + radialTimeShift());
if (timer && _radial.animating()) {
updateBackgroundRect();
}
}
void SettingsInner::updateChatBackground() {
int32 size = st::setBackgroundSize * cIntRetinaFactor();
QImage back(size, size, QImage::Format_ARGB32_Premultiplied);
@ -1673,6 +1716,7 @@ void SettingsInner::updateChatBackground() {
_background = QPixmap::fromImage(back);
_background.setDevicePixelRatio(cRetinaFactor());
_needBackgroundUpdate = false;
updateBackgroundRect();
}
@ -1680,6 +1724,9 @@ void SettingsInner::needBackgroundUpdate(bool tile) {
_needBackgroundUpdate = true;
_tileBackground.setChecked(tile);
updateChatBackground();
if (radialLoading()) {
radialStart();
}
}
void SettingsInner::onTileBackground() {

View File

@ -285,6 +285,15 @@ private:
FlatCheckbox _tileBackground, _adaptiveForWide;
bool _needBackgroundUpdate;
// Radial animation interface.
RadialAnimation _radial;
float64 radialProgress() const;
bool radialLoading() const;
QRect radialRect() const;
void radialStart();
uint64 radialTimeShift() const;
void step_radial(uint64 ms, bool timer);
// advanced
LinkButton _passcodeEdit, _passcodeTurnOff, _autoLock;
QString _autoLockText;