Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
914afb131d
@ -8,6 +8,13 @@ find_package(Qt5Widgets REQUIRED)
|
|||||||
find_package(Qt5Network REQUIRED)
|
find_package(Qt5Network REQUIRED)
|
||||||
find_package(Qt5LinguistTools REQUIRED)
|
find_package(Qt5LinguistTools REQUIRED)
|
||||||
|
|
||||||
|
if (Qt5Widgets_FOUND)
|
||||||
|
if (Qt5Widgets_VERSION VERSION_LESS 5.7.0)
|
||||||
|
message(STATUS "Qt version ${Qt5Widgets_VERSION}")
|
||||||
|
message(WARNING "Minimum supported Qt5 version is 5.7!")
|
||||||
|
endif()
|
||||||
|
endif(Qt5Widgets_FOUND)
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER gcc)
|
set(CMAKE_C_COMPILER gcc)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
@ -51,7 +58,6 @@ message(STATUS "Version: ${PROJECT_VERSION}")
|
|||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
|
||||||
-std=c++11 \
|
|
||||||
-Wall \
|
-Wall \
|
||||||
-Wextra \
|
-Wextra \
|
||||||
-Werror \
|
-Werror \
|
||||||
@ -72,6 +78,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SRC_FILES
|
set(SRC_FILES
|
||||||
|
src/AvatarProvider.cc
|
||||||
src/ChatPage.cc
|
src/ChatPage.cc
|
||||||
src/Deserializable.cc
|
src/Deserializable.cc
|
||||||
src/EmojiCategory.cc
|
src/EmojiCategory.cc
|
||||||
@ -88,6 +95,7 @@ set(SRC_FILES
|
|||||||
src/Login.cc
|
src/Login.cc
|
||||||
src/LoginPage.cc
|
src/LoginPage.cc
|
||||||
src/LoginSettings.cc
|
src/LoginSettings.cc
|
||||||
|
src/LogoutDialog.cc
|
||||||
src/MainWindow.cc
|
src/MainWindow.cc
|
||||||
src/MatrixClient.cc
|
src/MatrixClient.cc
|
||||||
src/Profile.cc
|
src/Profile.cc
|
||||||
@ -153,6 +161,7 @@ include_directories(include/events)
|
|||||||
include_directories(include/events/messages)
|
include_directories(include/events/messages)
|
||||||
|
|
||||||
qt5_wrap_cpp(MOC_HEADERS
|
qt5_wrap_cpp(MOC_HEADERS
|
||||||
|
include/AvatarProvider.h
|
||||||
include/ChatPage.h
|
include/ChatPage.h
|
||||||
include/EmojiCategory.h
|
include/EmojiCategory.h
|
||||||
include/EmojiItemDelegate.h
|
include/EmojiItemDelegate.h
|
||||||
@ -165,6 +174,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
|||||||
include/TimelineViewManager.h
|
include/TimelineViewManager.h
|
||||||
include/LoginPage.h
|
include/LoginPage.h
|
||||||
include/LoginSettings.h
|
include/LoginSettings.h
|
||||||
|
include/LogoutDialog.h
|
||||||
include/MainWindow.h
|
include/MainWindow.h
|
||||||
include/MatrixClient.h
|
include/MatrixClient.h
|
||||||
include/RegisterPage.h
|
include/RegisterPage.h
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
nheko
|
nheko
|
||||||
----
|
----
|
||||||
[](https://travis-ci.org/mujx/nheko) [](https://ci.appveyor.com/project/mujx/nheko/branch/master)
|
[](https://travis-ci.org/mujx/nheko) [](https://ci.appveyor.com/project/mujx/nheko/branch/master) [](https://translate.nordgedanken.de/projects/nheko/nheko/)
|
||||||
|
|
||||||
The motivation behind the project is to provide a native desktop app for [Matrix] that
|
The motivation behind the project is to provide a native desktop app for [Matrix] that
|
||||||
feels more like a mainstream chat app ([Riot], Telegram etc) and less like an IRC client.
|
feels more like a mainstream chat app ([Riot], Telegram etc) and less like an IRC client.
|
||||||
|
47
include/AvatarProvider.h
Normal file
47
include/AvatarProvider.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "MatrixClient.h"
|
||||||
|
#include "TimelineItem.h"
|
||||||
|
|
||||||
|
class AvatarProvider : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void init(QSharedPointer<MatrixClient> client);
|
||||||
|
static void resolve(const QString &userId, TimelineItem *item);
|
||||||
|
static void setAvatarUrl(const QString &userId, const QUrl &url);
|
||||||
|
|
||||||
|
static void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void updateAvatar(const QString &uid, const QImage &img);
|
||||||
|
|
||||||
|
static QSharedPointer<MatrixClient> client_;
|
||||||
|
static QMap<QString, QList<TimelineItem *>> toBeResolved_;
|
||||||
|
|
||||||
|
static QMap<QString, QImage> userAvatars_;
|
||||||
|
static QMap<QString, QUrl> avatarUrls_;
|
||||||
|
};
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "RoomList.h"
|
#include "RoomList.h"
|
||||||
|
#include "RoomSettings.h"
|
||||||
#include "RoomState.h"
|
#include "RoomState.h"
|
||||||
#include "Splitter.h"
|
#include "Splitter.h"
|
||||||
#include "TextInputWidget.h"
|
#include "TextInputWidget.h"
|
||||||
@ -92,6 +93,7 @@ private:
|
|||||||
UserInfoWidget *user_info_widget_;
|
UserInfoWidget *user_info_widget_;
|
||||||
|
|
||||||
QMap<QString, RoomState> state_manager_;
|
QMap<QString, RoomState> state_manager_;
|
||||||
|
QMap<QString, QSharedPointer<RoomSettings>> settingsManager_;
|
||||||
|
|
||||||
// Matrix Client API provider.
|
// Matrix Client API provider.
|
||||||
QSharedPointer<MatrixClient> client_;
|
QSharedPointer<MatrixClient> client_;
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QFrame>
|
|
||||||
#include <QGraphicsOpacityEffect>
|
#include <QGraphicsOpacityEffect>
|
||||||
#include <QParallelAnimationGroup>
|
|
||||||
#include <QPropertyAnimation>
|
#include <QPropertyAnimation>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@ -27,7 +25,7 @@
|
|||||||
#include "EmojiCategory.h"
|
#include "EmojiCategory.h"
|
||||||
#include "EmojiProvider.h"
|
#include "EmojiProvider.h"
|
||||||
|
|
||||||
class EmojiPanel : public QFrame
|
class EmojiPanel : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -43,25 +41,24 @@ signals:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void leaveEvent(QEvent *event);
|
void leaveEvent(QEvent *event);
|
||||||
|
void paintEvent(QPaintEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void showEmojiCategory(const EmojiCategory *category);
|
void showEmojiCategory(const EmojiCategory *category);
|
||||||
|
|
||||||
QPropertyAnimation *opacity_anim_;
|
QPropertyAnimation *animation_;
|
||||||
QPropertyAnimation *size_anim_;
|
|
||||||
QGraphicsOpacityEffect *opacity_;
|
QGraphicsOpacityEffect *opacity_;
|
||||||
QParallelAnimationGroup *animation_;
|
|
||||||
|
|
||||||
EmojiProvider emoji_provider_;
|
EmojiProvider emoji_provider_;
|
||||||
|
|
||||||
QScrollArea *scroll_area_;
|
QScrollArea *scrollArea_;
|
||||||
|
|
||||||
|
int shadowMargin_;
|
||||||
|
|
||||||
// Panel dimensions.
|
// Panel dimensions.
|
||||||
const int WIDTH = 370;
|
int width_;
|
||||||
const int HEIGHT = 350;
|
int height_;
|
||||||
|
|
||||||
const int ANIMATION_DURATION = 100;
|
int animationDuration_;
|
||||||
const int ANIMATION_OFFSET = 50;
|
int categoryIconSize_;
|
||||||
|
|
||||||
const int category_icon_size_ = 20;
|
|
||||||
};
|
};
|
||||||
|
36
include/LogoutDialog.h
Normal file
36
include/LogoutDialog.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
#include "FlatButton.h"
|
||||||
|
|
||||||
|
class LogoutDialog : public QFrame
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit LogoutDialog(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void closing(bool isLoggingOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FlatButton *confirmBtn_;
|
||||||
|
FlatButton *cancelBtn_;
|
||||||
|
};
|
@ -38,6 +38,8 @@ public:
|
|||||||
explicit MainWindow(QWidget *parent = 0);
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
static MainWindow *instance();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
@ -62,6 +64,8 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
bool hasActiveUser();
|
bool hasActiveUser();
|
||||||
|
|
||||||
|
static MainWindow *instance_;
|
||||||
|
|
||||||
// The initial welcome screen.
|
// The initial welcome screen.
|
||||||
WelcomePage *welcome_page_;
|
WelcomePage *welcome_page_;
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
void registerUser(const QString &username, const QString &password, const QString &server) noexcept;
|
void registerUser(const QString &username, const QString &password, const QString &server) noexcept;
|
||||||
void versions() noexcept;
|
void versions() noexcept;
|
||||||
void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
|
void fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url);
|
||||||
|
void fetchUserAvatar(const QString &userId, const QUrl &avatarUrl);
|
||||||
void fetchOwnAvatar(const QUrl &avatar_url);
|
void fetchOwnAvatar(const QUrl &avatar_url);
|
||||||
void downloadImage(const QString &event_id, const QUrl &url);
|
void downloadImage(const QString &event_id, const QUrl &url);
|
||||||
void messages(const QString &room_id, const QString &from_token) noexcept;
|
void messages(const QString &room_id, const QString &from_token) noexcept;
|
||||||
@ -69,6 +70,7 @@ signals:
|
|||||||
void registerSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
void registerSuccess(const QString &userid, const QString &homeserver, const QString &token);
|
||||||
|
|
||||||
void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
|
void roomAvatarRetrieved(const QString &roomid, const QPixmap &img);
|
||||||
|
void userAvatarRetrieved(const QString &userId, const QImage &img);
|
||||||
void ownAvatarRetrieved(const QPixmap &img);
|
void ownAvatarRetrieved(const QPixmap &img);
|
||||||
void imageDownloaded(const QString &event_id, const QPixmap &img);
|
void imageDownloaded(const QString &event_id, const QPixmap &img);
|
||||||
|
|
||||||
@ -95,6 +97,7 @@ private:
|
|||||||
Messages,
|
Messages,
|
||||||
Register,
|
Register,
|
||||||
RoomAvatar,
|
RoomAvatar,
|
||||||
|
UserAvatar,
|
||||||
SendTextMessage,
|
SendTextMessage,
|
||||||
Sync,
|
Sync,
|
||||||
Versions,
|
Versions,
|
||||||
@ -111,6 +114,7 @@ private:
|
|||||||
void onInitialSyncResponse(QNetworkReply *reply);
|
void onInitialSyncResponse(QNetworkReply *reply);
|
||||||
void onSyncResponse(QNetworkReply *reply);
|
void onSyncResponse(QNetworkReply *reply);
|
||||||
void onRoomAvatarResponse(QNetworkReply *reply);
|
void onRoomAvatarResponse(QNetworkReply *reply);
|
||||||
|
void onUserAvatarResponse(QNetworkReply *reply);
|
||||||
void onImageResponse(QNetworkReply *reply);
|
void onImageResponse(QNetworkReply *reply);
|
||||||
void onMessagesResponse(QNetworkReply *reply);
|
void onMessagesResponse(QNetworkReply *reply);
|
||||||
|
|
||||||
|
@ -17,9 +17,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "Menu.h"
|
||||||
#include "RippleOverlay.h"
|
#include "RippleOverlay.h"
|
||||||
|
#include "RoomSettings.h"
|
||||||
#include "RoomState.h"
|
#include "RoomState.h"
|
||||||
|
|
||||||
class RoomInfoListItem : public QWidget
|
class RoomInfoListItem : public QWidget
|
||||||
@ -27,7 +31,11 @@ class RoomInfoListItem : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RoomInfoListItem(RoomState state, QString room_id, QWidget *parent = 0);
|
RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
||||||
|
RoomState state,
|
||||||
|
QString room_id,
|
||||||
|
QWidget *parent = 0);
|
||||||
|
|
||||||
~RoomInfoListItem();
|
~RoomInfoListItem();
|
||||||
|
|
||||||
void updateUnreadMessageCount(int count);
|
void updateUnreadMessageCount(int count);
|
||||||
@ -48,8 +56,11 @@ public slots:
|
|||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString notificationText();
|
||||||
|
|
||||||
const int Padding = 7;
|
const int Padding = 7;
|
||||||
const int IconSize = 46;
|
const int IconSize = 46;
|
||||||
|
|
||||||
@ -64,6 +75,11 @@ private:
|
|||||||
|
|
||||||
QPixmap roomAvatar_;
|
QPixmap roomAvatar_;
|
||||||
|
|
||||||
|
Menu *menu_;
|
||||||
|
QAction *toggleNotifications_;
|
||||||
|
|
||||||
|
QSharedPointer<RoomSettings> roomSettings_;
|
||||||
|
|
||||||
bool isPressed_ = false;
|
bool isPressed_ = false;
|
||||||
|
|
||||||
int maxHeight_;
|
int maxHeight_;
|
||||||
|
@ -35,7 +35,8 @@ public:
|
|||||||
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
|
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
|
||||||
~RoomList();
|
~RoomList();
|
||||||
|
|
||||||
void setInitialRooms(const QMap<QString, RoomState> &states);
|
void setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||||
|
const QMap<QString, RoomState> &states);
|
||||||
void sync(const QMap<QString, RoomState> &states);
|
void sync(const QMap<QString, RoomState> &states);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
55
include/RoomSettings.h
Normal file
55
include/RoomSettings.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
class RoomSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RoomSettings(QString room_id)
|
||||||
|
{
|
||||||
|
path_ = QString("notifications/%1").arg(room_id);
|
||||||
|
isNotificationsEnabled_ = true;
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
|
||||||
|
if (settings.contains(path_))
|
||||||
|
isNotificationsEnabled_ = settings.value(path_).toBool();
|
||||||
|
else
|
||||||
|
settings.setValue(path_, isNotificationsEnabled_);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isNotificationsEnabled()
|
||||||
|
{
|
||||||
|
return isNotificationsEnabled_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void toggleNotifications()
|
||||||
|
{
|
||||||
|
isNotificationsEnabled_ = !isNotificationsEnabled_;
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue(path_, isNotificationsEnabled_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString path_;
|
||||||
|
|
||||||
|
bool isNotificationsEnabled_;
|
||||||
|
};
|
@ -24,6 +24,7 @@
|
|||||||
#include "ImageItem.h"
|
#include "ImageItem.h"
|
||||||
#include "Sync.h"
|
#include "Sync.h"
|
||||||
|
|
||||||
|
#include "Avatar.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "MessageEvent.h"
|
#include "MessageEvent.h"
|
||||||
#include "Notice.h"
|
#include "Notice.h"
|
||||||
@ -46,19 +47,35 @@ public:
|
|||||||
TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, const QString &color, QWidget *parent);
|
TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, const QString &color, QWidget *parent);
|
||||||
TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, QWidget *parent);
|
TimelineItem(ImageItem *img, const events::MessageEvent<msgs::Image> &e, QWidget *parent);
|
||||||
|
|
||||||
|
void setUserAvatar(const QImage &pixmap);
|
||||||
|
|
||||||
~TimelineItem();
|
~TimelineItem();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init();
|
||||||
|
|
||||||
void generateBody(const QString &body);
|
void generateBody(const QString &body);
|
||||||
void generateBody(const QString &userid, const QString &color, const QString &body);
|
void generateBody(const QString &userid, const QString &color, const QString &body);
|
||||||
void generateTimestamp(const QDateTime &time);
|
void generateTimestamp(const QDateTime &time);
|
||||||
|
|
||||||
|
void setupAvatarLayout(const QString &userName);
|
||||||
|
void setupSimpleLayout();
|
||||||
|
|
||||||
QString replaceEmoji(const QString &body);
|
QString replaceEmoji(const QString &body);
|
||||||
|
|
||||||
void setupLayout();
|
QHBoxLayout *topLayout_;
|
||||||
|
QVBoxLayout *sideLayout_; // Avatar or Timestamp
|
||||||
|
QVBoxLayout *mainLayout_; // Header & Message body
|
||||||
|
|
||||||
QHBoxLayout *top_layout_;
|
QHBoxLayout *headerLayout_; // Username (&) Timestamp
|
||||||
|
|
||||||
QLabel *time_label_;
|
Avatar *userAvatar_;
|
||||||
QLabel *content_label_;
|
|
||||||
|
QLabel *timestamp_;
|
||||||
|
QLabel *userName_;
|
||||||
|
QLabel *body_;
|
||||||
|
|
||||||
|
QFont bodyFont_;
|
||||||
|
QFont usernameFont_;
|
||||||
|
QFont timestampFont_;
|
||||||
};
|
};
|
||||||
|
@ -17,15 +17,20 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDebug>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPaintEvent>
|
#include <QPaintEvent>
|
||||||
|
#include <QSharedPointer>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
#include "RoomSettings.h"
|
||||||
|
|
||||||
class TopRoomBar : public QWidget
|
class TopRoomBar : public QWidget
|
||||||
{
|
{
|
||||||
@ -39,6 +44,7 @@ public:
|
|||||||
inline void updateRoomName(const QString &name);
|
inline void updateRoomName(const QString &name);
|
||||||
inline void updateRoomTopic(const QString &topic);
|
inline void updateRoomTopic(const QString &topic);
|
||||||
void updateRoomAvatarFromName(const QString &name);
|
void updateRoomAvatarFromName(const QString &name);
|
||||||
|
void setRoomSettings(QSharedPointer<RoomSettings> settings);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
@ -52,10 +58,16 @@ private:
|
|||||||
QLabel *name_label_;
|
QLabel *name_label_;
|
||||||
QLabel *topic_label_;
|
QLabel *topic_label_;
|
||||||
|
|
||||||
FlatButton *search_button_;
|
QSharedPointer<RoomSettings> roomSettings_;
|
||||||
FlatButton *settings_button_;
|
|
||||||
|
QMenu *menu_;
|
||||||
|
QAction *toggleNotifications_;
|
||||||
|
|
||||||
|
FlatButton *settingsBtn_;
|
||||||
|
|
||||||
Avatar *avatar_;
|
Avatar *avatar_;
|
||||||
|
|
||||||
|
int buttonSize_;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void TopRoomBar::updateRoomAvatar(const QImage &avatar_image)
|
inline void TopRoomBar::updateRoomAvatar(const QImage &avatar_image)
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
#include "LogoutDialog.h"
|
||||||
|
#include "OverlayModal.h"
|
||||||
|
|
||||||
class UserInfoWidget : public QWidget
|
class UserInfoWidget : public QWidget
|
||||||
{
|
{
|
||||||
@ -45,6 +47,9 @@ signals:
|
|||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void closeLogoutDialog(bool isLoggingOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Avatar *userAvatar_;
|
Avatar *userAvatar_;
|
||||||
|
|
||||||
@ -62,4 +67,9 @@ private:
|
|||||||
QString user_id_;
|
QString user_id_;
|
||||||
|
|
||||||
QImage avatar_image_;
|
QImage avatar_image_;
|
||||||
|
|
||||||
|
OverlayModal *logoutModal_;
|
||||||
|
LogoutDialog *logoutDialog_;
|
||||||
|
|
||||||
|
int logoutButtonSize_;
|
||||||
};
|
};
|
||||||
|
100
include/ui/DropShadow.h
Normal file
100
include/ui/DropShadow.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QLinearGradient>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
class DropShadow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void draw(QPainter &painter,
|
||||||
|
qint16 margin,
|
||||||
|
qreal radius,
|
||||||
|
QColor start,
|
||||||
|
QColor end,
|
||||||
|
qreal startPosition,
|
||||||
|
qreal endPosition0,
|
||||||
|
qreal endPosition1,
|
||||||
|
qreal width,
|
||||||
|
qreal height)
|
||||||
|
{
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
|
||||||
|
QLinearGradient gradient;
|
||||||
|
gradient.setColorAt(startPosition, start);
|
||||||
|
gradient.setColorAt(endPosition0, end);
|
||||||
|
|
||||||
|
// Right
|
||||||
|
QPointF right0(width - margin, height / 2);
|
||||||
|
QPointF right1(width, height / 2);
|
||||||
|
gradient.setStart(right0);
|
||||||
|
gradient.setFinalStop(right1);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)), 0.0, 0.0);
|
||||||
|
|
||||||
|
// Left
|
||||||
|
QPointF left0(margin, height / 2);
|
||||||
|
QPointF left1(0, height / 2);
|
||||||
|
gradient.setStart(left0);
|
||||||
|
gradient.setFinalStop(left1);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
|
||||||
|
|
||||||
|
// Top
|
||||||
|
QPointF top0(width / 2, margin);
|
||||||
|
QPointF top1(width / 2, 0);
|
||||||
|
gradient.setStart(top0);
|
||||||
|
gradient.setFinalStop(top1);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
QPointF bottom0(width / 2, height - margin);
|
||||||
|
QPointF bottom1(width / 2, height);
|
||||||
|
gradient.setStart(bottom0);
|
||||||
|
gradient.setFinalStop(bottom1);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
|
||||||
|
|
||||||
|
// BottomRight
|
||||||
|
QPointF bottomright0(width - margin, height - margin);
|
||||||
|
QPointF bottomright1(width, height);
|
||||||
|
gradient.setStart(bottomright0);
|
||||||
|
gradient.setFinalStop(bottomright1);
|
||||||
|
gradient.setColorAt(endPosition1, end);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
|
||||||
|
|
||||||
|
// BottomLeft
|
||||||
|
QPointF bottomleft0(margin, height - margin);
|
||||||
|
QPointF bottomleft1(0, height);
|
||||||
|
gradient.setStart(bottomleft0);
|
||||||
|
gradient.setFinalStop(bottomleft1);
|
||||||
|
gradient.setColorAt(endPosition1, end);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
|
||||||
|
|
||||||
|
// TopLeft
|
||||||
|
QPointF topleft0(margin, margin);
|
||||||
|
QPointF topleft1(0, 0);
|
||||||
|
gradient.setStart(topleft0);
|
||||||
|
gradient.setFinalStop(topleft1);
|
||||||
|
gradient.setColorAt(endPosition1, end);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(topleft0, topleft1), 0.0, 0.0);
|
||||||
|
|
||||||
|
// TopRight
|
||||||
|
QPointF topright0(width - margin, margin);
|
||||||
|
QPointF topright1(width, 0);
|
||||||
|
gradient.setStart(topright0);
|
||||||
|
gradient.setFinalStop(topright1);
|
||||||
|
gradient.setColorAt(endPosition1, end);
|
||||||
|
painter.setBrush(QBrush(gradient));
|
||||||
|
painter.drawRoundRect(QRectF(topright0, topright1), 0.0, 0.0);
|
||||||
|
|
||||||
|
// Widget
|
||||||
|
painter.setBrush(QBrush("#FFFFFF"));
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
painter.drawRoundRect(QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)), radius, radius);
|
||||||
|
}
|
||||||
|
};
|
25
include/ui/Menu.h
Normal file
25
include/ui/Menu.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
|
class Menu : public QMenu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Menu(QWidget *parent = nullptr)
|
||||||
|
: QMenu(parent)
|
||||||
|
{
|
||||||
|
setFont(QFont("Open Sans", 10));
|
||||||
|
setStyleSheet(
|
||||||
|
"QMenu { color: black; background-color: white; margin: 0px;}"
|
||||||
|
"QMenu::item { color: black; padding: 7px 20px; border: 1px solid transparent; margin: 2px 0px; }"
|
||||||
|
"QMenu::item:selected { color: black; background: rgba(180, 180, 180, 100); }");
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void leaveEvent(QEvent *e)
|
||||||
|
{
|
||||||
|
Q_UNUSED(e);
|
||||||
|
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
};
|
BIN
resources/icons/vertical-ellipsis.png
Normal file
BIN
resources/icons/vertical-ellipsis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 509 B |
@ -22,6 +22,7 @@
|
|||||||
<file>icons/emoji-categories/symbols.png</file>
|
<file>icons/emoji-categories/symbols.png</file>
|
||||||
<file>icons/emoji-categories/flags.png</file>
|
<file>icons/emoji-categories/flags.png</file>
|
||||||
|
|
||||||
|
<file>icons/vertical-ellipsis.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
||||||
<qresource prefix="/logos">
|
<qresource prefix="/logos">
|
||||||
|
83
src/AvatarProvider.cc
Normal file
83
src/AvatarProvider.cc
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AvatarProvider.h"
|
||||||
|
|
||||||
|
QSharedPointer<MatrixClient> AvatarProvider::client_;
|
||||||
|
|
||||||
|
QMap<QString, QImage> AvatarProvider::userAvatars_;
|
||||||
|
QMap<QString, QUrl> AvatarProvider::avatarUrls_;
|
||||||
|
QMap<QString, QList<TimelineItem *>> AvatarProvider::toBeResolved_;
|
||||||
|
|
||||||
|
void AvatarProvider::init(QSharedPointer<MatrixClient> client)
|
||||||
|
{
|
||||||
|
client_ = client;
|
||||||
|
|
||||||
|
connect(client_.data(), &MatrixClient::userAvatarRetrieved, &AvatarProvider::updateAvatar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarProvider::updateAvatar(const QString &uid, const QImage &img)
|
||||||
|
{
|
||||||
|
if (toBeResolved_.contains(uid)) {
|
||||||
|
auto items = toBeResolved_[uid];
|
||||||
|
|
||||||
|
// Update all the timeline items with the resolved avatar.
|
||||||
|
for (const auto item : items)
|
||||||
|
item->setUserAvatar(img);
|
||||||
|
|
||||||
|
toBeResolved_.remove(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
userAvatars_.insert(uid, img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarProvider::resolve(const QString &userId, TimelineItem *item)
|
||||||
|
{
|
||||||
|
if (userAvatars_.contains(userId)) {
|
||||||
|
auto img = userAvatars_[userId];
|
||||||
|
|
||||||
|
item->setUserAvatar(img);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avatarUrls_.contains(userId)) {
|
||||||
|
// Add the current timeline item to the waiting list for this avatar.
|
||||||
|
if (!toBeResolved_.contains(userId)) {
|
||||||
|
client_->fetchUserAvatar(userId, avatarUrls_[userId]);
|
||||||
|
|
||||||
|
QList<TimelineItem *> timelineItems;
|
||||||
|
timelineItems.push_back(item);
|
||||||
|
|
||||||
|
toBeResolved_.insert(userId, timelineItems);
|
||||||
|
} else {
|
||||||
|
toBeResolved_[userId].push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarProvider::setAvatarUrl(const QString &userId, const QUrl &url)
|
||||||
|
{
|
||||||
|
avatarUrls_.insert(userId, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AvatarProvider::clear()
|
||||||
|
{
|
||||||
|
userAvatars_.clear();
|
||||||
|
avatarUrls_.clear();
|
||||||
|
toBeResolved_.clear();
|
||||||
|
}
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "AliasesEventContent.h"
|
#include "AliasesEventContent.h"
|
||||||
#include "AvatarEventContent.h"
|
#include "AvatarEventContent.h"
|
||||||
|
#include "AvatarProvider.h"
|
||||||
#include "CanonicalAliasEventContent.h"
|
#include "CanonicalAliasEventContent.h"
|
||||||
#include "CreateEventContent.h"
|
#include "CreateEventContent.h"
|
||||||
#include "HistoryVisibilityEventContent.h"
|
#include "HistoryVisibilityEventContent.h"
|
||||||
@ -127,10 +128,16 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
connect(room_list_, &RoomList::roomChanged, this, &ChatPage::changeTopRoomInfo);
|
||||||
connect(room_list_, &RoomList::roomChanged, view_manager_, &TimelineViewManager::setHistoryView);
|
connect(room_list_, &RoomList::roomChanged, view_manager_, &TimelineViewManager::setHistoryView);
|
||||||
|
|
||||||
connect(view_manager_,
|
connect(view_manager_, &TimelineViewManager::unreadMessages, this, [=](const QString &roomid, int count) {
|
||||||
SIGNAL(unreadMessages(const QString &, int)),
|
if (!settingsManager_.contains(roomid)) {
|
||||||
room_list_,
|
qWarning() << "RoomId does not have settings" << roomid;
|
||||||
SLOT(updateUnreadMessageCount(const QString &, int)));
|
room_list_->updateUnreadMessageCount(roomid, count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsManager_[roomid]->isNotificationsEnabled())
|
||||||
|
room_list_->updateUnreadMessageCount(roomid, count);
|
||||||
|
});
|
||||||
|
|
||||||
connect(room_list_,
|
connect(room_list_,
|
||||||
SIGNAL(totalUnreadMessageCountUpdated(int)),
|
SIGNAL(totalUnreadMessageCountUpdated(int)),
|
||||||
@ -167,17 +174,25 @@ ChatPage::ChatPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
SIGNAL(ownAvatarRetrieved(const QPixmap &)),
|
SIGNAL(ownAvatarRetrieved(const QPixmap &)),
|
||||||
this,
|
this,
|
||||||
SLOT(setOwnAvatar(const QPixmap &)));
|
SLOT(setOwnAvatar(const QPixmap &)));
|
||||||
|
|
||||||
|
AvatarProvider::init(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPage::logout()
|
void ChatPage::logout()
|
||||||
{
|
{
|
||||||
sync_timer_->stop();
|
sync_timer_->stop();
|
||||||
|
|
||||||
|
// Delete all config parameters.
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.remove("auth/access_token");
|
settings.beginGroup("auth");
|
||||||
settings.remove("auth/home_server");
|
settings.remove("");
|
||||||
settings.remove("auth/user_id");
|
settings.endGroup();
|
||||||
settings.remove("client/transaction_id");
|
settings.beginGroup("client");
|
||||||
|
settings.remove("");
|
||||||
|
settings.endGroup();
|
||||||
|
settings.beginGroup("notifications");
|
||||||
|
settings.remove("");
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
// Clear the environment.
|
// Clear the environment.
|
||||||
room_list_->clear();
|
room_list_->clear();
|
||||||
@ -188,8 +203,11 @@ void ChatPage::logout()
|
|||||||
client_->reset();
|
client_->reset();
|
||||||
|
|
||||||
state_manager_.clear();
|
state_manager_.clear();
|
||||||
|
settingsManager_.clear();
|
||||||
room_avatars_.clear();
|
room_avatars_.clear();
|
||||||
|
|
||||||
|
AvatarProvider::clear();
|
||||||
|
|
||||||
emit close();
|
emit close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,10 +304,19 @@ void ChatPage::initialSyncCompleted(const SyncResponse &response)
|
|||||||
updateDisplayNames(room_state);
|
updateDisplayNames(room_state);
|
||||||
|
|
||||||
state_manager_.insert(it.key(), room_state);
|
state_manager_.insert(it.key(), room_state);
|
||||||
|
settingsManager_.insert(it.key(), QSharedPointer<RoomSettings>(new RoomSettings(it.key())));
|
||||||
|
|
||||||
|
for (const auto membership : room_state.memberships) {
|
||||||
|
auto uid = membership.sender();
|
||||||
|
auto url = membership.content().avatarUrl();
|
||||||
|
|
||||||
|
if (!url.toString().isEmpty())
|
||||||
|
AvatarProvider::setAvatarUrl(uid, url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view_manager_->initialize(response.rooms());
|
view_manager_->initialize(response.rooms());
|
||||||
room_list_->setInitialRooms(state_manager_);
|
room_list_->setInitialRooms(settingsManager_, state_manager_);
|
||||||
|
|
||||||
sync_timer_->start(sync_interval_);
|
sync_timer_->start(sync_interval_);
|
||||||
}
|
}
|
||||||
@ -325,6 +352,7 @@ void ChatPage::changeTopRoomInfo(const QString &room_id)
|
|||||||
|
|
||||||
top_bar_->updateRoomName(state.getName());
|
top_bar_->updateRoomName(state.getName());
|
||||||
top_bar_->updateRoomTopic(state.getTopic());
|
top_bar_->updateRoomTopic(state.getTopic());
|
||||||
|
top_bar_->setRoomSettings(settingsManager_[room_id]);
|
||||||
|
|
||||||
if (room_avatars_.contains(room_id))
|
if (room_avatars_.contains(room_id))
|
||||||
top_bar_->updateRoomAvatar(room_avatars_.value(room_id).toImage());
|
top_bar_->updateRoomAvatar(room_avatars_.value(room_id).toImage());
|
||||||
|
@ -15,20 +15,24 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
|
#include "DropShadow.h"
|
||||||
#include "EmojiCategory.h"
|
#include "EmojiCategory.h"
|
||||||
#include "EmojiPanel.h"
|
#include "EmojiPanel.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
|
||||||
EmojiPanel::EmojiPanel(QWidget *parent)
|
EmojiPanel::EmojiPanel(QWidget *parent)
|
||||||
: QFrame(parent)
|
: QWidget(parent)
|
||||||
|
, shadowMargin_{2}
|
||||||
|
, width_{370}
|
||||||
|
, height_{350}
|
||||||
|
, animationDuration_{100}
|
||||||
|
, categoryIconSize_{20}
|
||||||
{
|
{
|
||||||
setStyleSheet(
|
setStyleSheet(
|
||||||
"QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}"
|
"QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}"
|
||||||
@ -40,172 +44,158 @@ EmojiPanel::EmojiPanel(QWidget *parent)
|
|||||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
|
setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
|
||||||
|
|
||||||
// TODO: Make it MainWindow aware
|
auto mainWidget = new QWidget(this);
|
||||||
auto main_frame_ = new QFrame(this);
|
mainWidget->setMaximumSize(width_, height_);
|
||||||
main_frame_->setMaximumSize(WIDTH, HEIGHT);
|
|
||||||
|
|
||||||
auto top_layout = new QVBoxLayout(this);
|
auto topLayout = new QVBoxLayout(this);
|
||||||
top_layout->addWidget(main_frame_);
|
topLayout->addWidget(mainWidget);
|
||||||
top_layout->setMargin(0);
|
topLayout->setMargin(shadowMargin_);
|
||||||
|
|
||||||
auto content_layout = new QVBoxLayout(main_frame_);
|
auto contentLayout = new QVBoxLayout(mainWidget);
|
||||||
content_layout->setMargin(0);
|
contentLayout->setMargin(0);
|
||||||
|
|
||||||
auto emoji_categories = new QFrame(main_frame_);
|
auto emojiCategories = new QFrame(mainWidget);
|
||||||
emoji_categories->setStyleSheet("background-color: #f2f2f2");
|
emojiCategories->setStyleSheet("background-color: #f2f2f2");
|
||||||
|
|
||||||
auto categories_layout = new QHBoxLayout(emoji_categories);
|
auto categoriesLayout = new QHBoxLayout(emojiCategories);
|
||||||
categories_layout->setSpacing(6);
|
categoriesLayout->setSpacing(6);
|
||||||
categories_layout->setMargin(5);
|
categoriesLayout->setMargin(5);
|
||||||
|
|
||||||
auto people_category = new FlatButton(emoji_categories);
|
auto peopleCategory = new FlatButton(emojiCategories);
|
||||||
people_category->setIcon(QIcon(":/icons/icons/emoji-categories/people.png"));
|
peopleCategory->setIcon(QIcon(":/icons/icons/emoji-categories/people.png"));
|
||||||
people_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
peopleCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
people_category->setForegroundColor("gray");
|
peopleCategory->setForegroundColor("gray");
|
||||||
|
|
||||||
auto nature_category = new FlatButton(emoji_categories);
|
auto natureCategory_ = new FlatButton(emojiCategories);
|
||||||
nature_category->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png"));
|
natureCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png"));
|
||||||
nature_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
natureCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
nature_category->setForegroundColor("gray");
|
natureCategory_->setForegroundColor("gray");
|
||||||
|
|
||||||
auto food_category = new FlatButton(emoji_categories);
|
auto foodCategory_ = new FlatButton(emojiCategories);
|
||||||
food_category->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png"));
|
foodCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png"));
|
||||||
food_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
foodCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
food_category->setForegroundColor("gray");
|
foodCategory_->setForegroundColor("gray");
|
||||||
|
|
||||||
auto activity_category = new FlatButton(emoji_categories);
|
auto activityCategory = new FlatButton(emojiCategories);
|
||||||
activity_category->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png"));
|
activityCategory->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png"));
|
||||||
activity_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
activityCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
activity_category->setForegroundColor("gray");
|
activityCategory->setForegroundColor("gray");
|
||||||
|
|
||||||
auto travel_category = new FlatButton(emoji_categories);
|
auto travelCategory = new FlatButton(emojiCategories);
|
||||||
travel_category->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png"));
|
travelCategory->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png"));
|
||||||
travel_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
travelCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
travel_category->setForegroundColor("gray");
|
travelCategory->setForegroundColor("gray");
|
||||||
|
|
||||||
auto objects_category = new FlatButton(emoji_categories);
|
auto objectsCategory = new FlatButton(emojiCategories);
|
||||||
objects_category->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png"));
|
objectsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png"));
|
||||||
objects_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
objectsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
objects_category->setForegroundColor("gray");
|
objectsCategory->setForegroundColor("gray");
|
||||||
|
|
||||||
auto symbols_category = new FlatButton(emoji_categories);
|
auto symbolsCategory = new FlatButton(emojiCategories);
|
||||||
symbols_category->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png"));
|
symbolsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png"));
|
||||||
symbols_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
symbolsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
symbols_category->setForegroundColor("gray");
|
symbolsCategory->setForegroundColor("gray");
|
||||||
|
|
||||||
auto flags_category = new FlatButton(emoji_categories);
|
auto flagsCategory = new FlatButton(emojiCategories);
|
||||||
flags_category->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png"));
|
flagsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png"));
|
||||||
flags_category->setIconSize(QSize(category_icon_size_, category_icon_size_));
|
flagsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
|
||||||
flags_category->setForegroundColor("gray");
|
flagsCategory->setForegroundColor("gray");
|
||||||
|
|
||||||
categories_layout->addWidget(people_category);
|
categoriesLayout->addWidget(peopleCategory);
|
||||||
categories_layout->addWidget(nature_category);
|
categoriesLayout->addWidget(natureCategory_);
|
||||||
categories_layout->addWidget(food_category);
|
categoriesLayout->addWidget(foodCategory_);
|
||||||
categories_layout->addWidget(activity_category);
|
categoriesLayout->addWidget(activityCategory);
|
||||||
categories_layout->addWidget(travel_category);
|
categoriesLayout->addWidget(travelCategory);
|
||||||
categories_layout->addWidget(objects_category);
|
categoriesLayout->addWidget(objectsCategory);
|
||||||
categories_layout->addWidget(symbols_category);
|
categoriesLayout->addWidget(symbolsCategory);
|
||||||
categories_layout->addWidget(flags_category);
|
categoriesLayout->addWidget(flagsCategory);
|
||||||
|
|
||||||
scroll_area_ = new QScrollArea(this);
|
scrollArea_ = new QScrollArea(this);
|
||||||
scroll_area_->setWidgetResizable(true);
|
scrollArea_->setWidgetResizable(true);
|
||||||
scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
|
||||||
auto scroll_widget_ = new QWidget(this);
|
auto scrollWidget = new QWidget(this);
|
||||||
auto scroll_layout_ = new QVBoxLayout(scroll_widget_);
|
auto scrollLayout = new QVBoxLayout(scrollWidget);
|
||||||
|
|
||||||
scroll_layout_->setMargin(0);
|
scrollLayout->setMargin(0);
|
||||||
scroll_area_->setWidget(scroll_widget_);
|
scrollArea_->setWidget(scrollWidget);
|
||||||
|
|
||||||
auto people_emoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scroll_widget_);
|
auto peopleEmoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scrollWidget);
|
||||||
scroll_layout_->addWidget(people_emoji);
|
scrollLayout->addWidget(peopleEmoji);
|
||||||
|
|
||||||
auto nature_emoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scroll_widget_);
|
auto natureEmoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scrollWidget);
|
||||||
scroll_layout_->addWidget(nature_emoji);
|
scrollLayout->addWidget(natureEmoji);
|
||||||
|
|
||||||
auto food_emoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scroll_widget_);
|
auto foodEmoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scrollWidget);
|
||||||
scroll_layout_->addWidget(food_emoji);
|
scrollLayout->addWidget(foodEmoji);
|
||||||
|
|
||||||
auto activity_emoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scroll_widget_);
|
auto activityEmoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scrollWidget);
|
||||||
scroll_layout_->addWidget(activity_emoji);
|
scrollLayout->addWidget(activityEmoji);
|
||||||
|
|
||||||
auto travel_emoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scroll_widget_);
|
auto travelEmoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scrollWidget);
|
||||||
scroll_layout_->addWidget(travel_emoji);
|
scrollLayout->addWidget(travelEmoji);
|
||||||
|
|
||||||
auto objects_emoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scroll_widget_);
|
auto objectsEmoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scrollWidget);
|
||||||
scroll_layout_->addWidget(objects_emoji);
|
scrollLayout->addWidget(objectsEmoji);
|
||||||
|
|
||||||
auto symbols_emoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scroll_widget_);
|
auto symbolsEmoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scrollWidget);
|
||||||
scroll_layout_->addWidget(symbols_emoji);
|
scrollLayout->addWidget(symbolsEmoji);
|
||||||
|
|
||||||
auto flags_emoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scroll_widget_);
|
auto flagsEmoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scrollWidget);
|
||||||
scroll_layout_->addWidget(flags_emoji);
|
scrollLayout->addWidget(flagsEmoji);
|
||||||
|
|
||||||
content_layout->addStretch(1);
|
contentLayout->addStretch(1);
|
||||||
content_layout->addWidget(scroll_area_);
|
contentLayout->addWidget(scrollArea_);
|
||||||
content_layout->addWidget(emoji_categories);
|
contentLayout->addWidget(emojiCategories);
|
||||||
|
|
||||||
setLayout(top_layout);
|
|
||||||
|
|
||||||
opacity_ = new QGraphicsOpacityEffect(this);
|
opacity_ = new QGraphicsOpacityEffect(this);
|
||||||
opacity_->setOpacity(1.0);
|
opacity_->setOpacity(1.0);
|
||||||
|
|
||||||
setGraphicsEffect(opacity_);
|
setGraphicsEffect(opacity_);
|
||||||
|
|
||||||
opacity_anim_ = new QPropertyAnimation(opacity_, "opacity", this);
|
animation_ = new QPropertyAnimation(opacity_, "opacity", this);
|
||||||
opacity_anim_->setDuration(ANIMATION_DURATION);
|
animation_->setDuration(animationDuration_);
|
||||||
opacity_anim_->setStartValue(1);
|
animation_->setStartValue(1);
|
||||||
opacity_anim_->setEndValue(0);
|
animation_->setEndValue(0);
|
||||||
|
|
||||||
size_anim_ = new QPropertyAnimation(this);
|
connect(peopleEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
size_anim_->setTargetObject(main_frame_);
|
connect(peopleCategory, &QPushButton::clicked, [this, peopleEmoji]() {
|
||||||
size_anim_->setPropertyName("geometry");
|
this->showEmojiCategory(peopleEmoji);
|
||||||
size_anim_->setDuration(ANIMATION_DURATION);
|
|
||||||
size_anim_->setStartValue(QRect(0, 0, WIDTH, HEIGHT));
|
|
||||||
size_anim_->setEndValue(QRect(ANIMATION_OFFSET, ANIMATION_OFFSET, WIDTH - ANIMATION_OFFSET, HEIGHT - ANIMATION_OFFSET));
|
|
||||||
|
|
||||||
animation_ = new QParallelAnimationGroup(this);
|
|
||||||
animation_->addAnimation(opacity_anim_);
|
|
||||||
animation_->addAnimation(size_anim_);
|
|
||||||
|
|
||||||
connect(people_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
|
||||||
connect(people_category, &QPushButton::clicked, [this, people_emoji]() {
|
|
||||||
this->showEmojiCategory(people_emoji);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(nature_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(natureEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(nature_category, &QPushButton::clicked, [this, nature_emoji]() {
|
connect(natureCategory_, &QPushButton::clicked, [this, natureEmoji]() {
|
||||||
this->showEmojiCategory(nature_emoji);
|
this->showEmojiCategory(natureEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(food_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(foodEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(food_category, &QPushButton::clicked, [this, food_emoji]() {
|
connect(foodCategory_, &QPushButton::clicked, [this, foodEmoji]() {
|
||||||
this->showEmojiCategory(food_emoji);
|
this->showEmojiCategory(foodEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(activity_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(activityEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(activity_category, &QPushButton::clicked, [this, activity_emoji]() {
|
connect(activityCategory, &QPushButton::clicked, [this, activityEmoji]() {
|
||||||
this->showEmojiCategory(activity_emoji);
|
this->showEmojiCategory(activityEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(travel_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(travelEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(travel_category, &QPushButton::clicked, [this, travel_emoji]() {
|
connect(travelCategory, &QPushButton::clicked, [this, travelEmoji]() {
|
||||||
this->showEmojiCategory(travel_emoji);
|
this->showEmojiCategory(travelEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(objects_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(objectsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(objects_category, &QPushButton::clicked, [this, objects_emoji]() {
|
connect(objectsCategory, &QPushButton::clicked, [this, objectsEmoji]() {
|
||||||
this->showEmojiCategory(objects_emoji);
|
this->showEmojiCategory(objectsEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(symbols_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(symbolsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(symbols_category, &QPushButton::clicked, [this, symbols_emoji]() {
|
connect(symbolsCategory, &QPushButton::clicked, [this, symbolsEmoji]() {
|
||||||
this->showEmojiCategory(symbols_emoji);
|
this->showEmojiCategory(symbolsEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(flags_emoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
connect(flagsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
|
||||||
connect(flags_category, &QPushButton::clicked, [this, flags_emoji]() {
|
connect(flagsCategory, &QPushButton::clicked, [this, flagsEmoji]() {
|
||||||
this->showEmojiCategory(flags_emoji);
|
this->showEmojiCategory(flagsEmoji);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(animation_, &QAbstractAnimation::finished, [this]() {
|
connect(animation_, &QAbstractAnimation::finished, [this]() {
|
||||||
@ -217,7 +207,7 @@ EmojiPanel::EmojiPanel(QWidget *parent)
|
|||||||
void EmojiPanel::showEmojiCategory(const EmojiCategory *category)
|
void EmojiPanel::showEmojiCategory(const EmojiCategory *category)
|
||||||
{
|
{
|
||||||
auto posToGo = category->mapToParent(QPoint()).y();
|
auto posToGo = category->mapToParent(QPoint()).y();
|
||||||
auto current = scroll_area_->verticalScrollBar()->value();
|
auto current = scrollArea_->verticalScrollBar()->value();
|
||||||
|
|
||||||
if (current == posToGo)
|
if (current == posToGo)
|
||||||
return;
|
return;
|
||||||
@ -228,10 +218,10 @@ void EmojiPanel::showEmojiCategory(const EmojiCategory *category)
|
|||||||
// To ensure the category is at the top, we move to the top
|
// To ensure the category is at the top, we move to the top
|
||||||
// and go as normal to the next category.
|
// and go as normal to the next category.
|
||||||
if (current > posToGo)
|
if (current > posToGo)
|
||||||
this->scroll_area_->ensureVisible(0, 0, 0, 0);
|
this->scrollArea_->ensureVisible(0, 0, 0, 0);
|
||||||
|
|
||||||
posToGo += 6 * 50;
|
posToGo += 6 * 50;
|
||||||
this->scroll_area_->ensureVisible(0, posToGo, 0, 0);
|
this->scrollArea_->ensureVisible(0, posToGo, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiPanel::leaveEvent(QEvent *event)
|
void EmojiPanel::leaveEvent(QEvent *event)
|
||||||
@ -241,6 +231,23 @@ void EmojiPanel::leaveEvent(QEvent *event)
|
|||||||
fadeOut();
|
fadeOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmojiPanel::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
QPainter p(this);
|
||||||
|
DropShadow::draw(p,
|
||||||
|
shadowMargin_,
|
||||||
|
4.0,
|
||||||
|
QColor(120, 120, 120, 92),
|
||||||
|
QColor(255, 255, 255, 0),
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
0.6,
|
||||||
|
width(),
|
||||||
|
height());
|
||||||
|
|
||||||
|
QWidget::paintEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
void EmojiPanel::fadeOut()
|
void EmojiPanel::fadeOut()
|
||||||
{
|
{
|
||||||
animation_->setDirection(QAbstractAnimation::Forward);
|
animation_->setDirection(QAbstractAnimation::Forward);
|
||||||
|
14
src/Login.cc
14
src/Login.cc
@ -34,10 +34,22 @@ LoginRequest::LoginRequest(QString username, QString password)
|
|||||||
|
|
||||||
QByteArray LoginRequest::serialize() noexcept
|
QByteArray LoginRequest::serialize() noexcept
|
||||||
{
|
{
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
QString initialDeviceName("nheko on Mac OS");
|
||||||
|
#elif defined(Q_OS_LINUX)
|
||||||
|
QString initialDeviceName("nheko on Linux");
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
QString initialDeviceName("nheko on Windows");
|
||||||
|
#else
|
||||||
|
QString initialDeviceName("nheko");
|
||||||
|
#endif
|
||||||
|
|
||||||
QJsonObject body{
|
QJsonObject body{
|
||||||
{"type", "m.login.password"},
|
{"type", "m.login.password"},
|
||||||
{"user", user_},
|
{"user", user_},
|
||||||
{"password", password_}};
|
{"password", password_},
|
||||||
|
{"initial_device_display_name", initialDeviceName},
|
||||||
|
};
|
||||||
|
|
||||||
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
return QJsonDocument(body).toJson(QJsonDocument::Compact);
|
||||||
}
|
}
|
||||||
|
@ -37,12 +37,10 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
back_button_ = new FlatButton(this);
|
back_button_ = new FlatButton(this);
|
||||||
back_button_->setMinimumSize(QSize(30, 30));
|
back_button_->setMinimumSize(QSize(30, 30));
|
||||||
back_button_->setForegroundColor("#333333");
|
back_button_->setForegroundColor("#333333");
|
||||||
back_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
|
|
||||||
advanced_settings_button_ = new FlatButton(this);
|
advanced_settings_button_ = new FlatButton(this);
|
||||||
advanced_settings_button_->setMinimumSize(QSize(30, 30));
|
advanced_settings_button_->setMinimumSize(QSize(30, 30));
|
||||||
advanced_settings_button_->setForegroundColor("#333333");
|
advanced_settings_button_->setForegroundColor("#333333");
|
||||||
advanced_settings_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
|
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||||
@ -105,7 +103,6 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
login_button_->setBackgroundColor(QColor("#333333"));
|
login_button_->setBackgroundColor(QColor("#333333"));
|
||||||
login_button_->setForegroundColor(QColor("white"));
|
login_button_->setForegroundColor(QColor("white"));
|
||||||
login_button_->setMinimumSize(350, 65);
|
login_button_->setMinimumSize(350, 65);
|
||||||
login_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
login_button_->setFontSize(17);
|
login_button_->setFontSize(17);
|
||||||
login_button_->setCornerRadius(3);
|
login_button_->setCornerRadius(3);
|
||||||
|
|
||||||
|
57
src/LogoutDialog.cc
Normal file
57
src/LogoutDialog.cc
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "LogoutDialog.h"
|
||||||
|
#include "Theme.h"
|
||||||
|
|
||||||
|
LogoutDialog::LogoutDialog(QWidget *parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
{
|
||||||
|
setMaximumSize(400, 400);
|
||||||
|
setStyleSheet("background-color: #f9f9f9");
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
layout->setSpacing(30);
|
||||||
|
layout->setMargin(20);
|
||||||
|
|
||||||
|
auto buttonLayout = new QHBoxLayout();
|
||||||
|
buttonLayout->setSpacing(0);
|
||||||
|
buttonLayout->setMargin(0);
|
||||||
|
|
||||||
|
confirmBtn_ = new FlatButton("OK", this);
|
||||||
|
confirmBtn_->setFontSize(12);
|
||||||
|
|
||||||
|
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
|
||||||
|
cancelBtn_->setFontSize(12);
|
||||||
|
|
||||||
|
buttonLayout->addStretch(1);
|
||||||
|
buttonLayout->addWidget(confirmBtn_);
|
||||||
|
buttonLayout->addWidget(cancelBtn_);
|
||||||
|
|
||||||
|
auto label = new QLabel(tr("Logout. Are you sure?"), this);
|
||||||
|
label->setFont(QFont("Open Sans", 14));
|
||||||
|
label->setStyleSheet("color: #333333");
|
||||||
|
|
||||||
|
layout->addWidget(label);
|
||||||
|
layout->addLayout(buttonLayout);
|
||||||
|
|
||||||
|
connect(confirmBtn_, &QPushButton::clicked, [=]() { emit closing(true); });
|
||||||
|
connect(cancelBtn_, &QPushButton::clicked, [=]() { emit closing(false); });
|
||||||
|
}
|
@ -22,6 +22,8 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
|
MainWindow *MainWindow::instance_ = nullptr;
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, progress_modal_{nullptr}
|
, progress_modal_{nullptr}
|
||||||
@ -148,6 +150,8 @@ void MainWindow::showChatPage(QString userid, QString homeserver, QString token)
|
|||||||
|
|
||||||
login_page_->reset();
|
login_page_->reset();
|
||||||
chat_page_->bootstrap(userid, homeserver, token);
|
chat_page_->bootstrap(userid, homeserver, token);
|
||||||
|
|
||||||
|
instance_ = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showWelcomePage()
|
void MainWindow::showWelcomePage()
|
||||||
@ -204,6 +208,11 @@ bool MainWindow::hasActiveUser()
|
|||||||
settings.contains("auth/user_id");
|
settings.contains("auth/user_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MainWindow *MainWindow::instance()
|
||||||
|
{
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -287,6 +287,29 @@ void MatrixClient::onRoomAvatarResponse(QNetworkReply *reply)
|
|||||||
emit roomAvatarRetrieved(roomid, pixmap);
|
emit roomAvatarRetrieved(roomid, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MatrixClient::onUserAvatarResponse(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
|
if (status == 0 || status >= 400) {
|
||||||
|
qWarning() << reply->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = reply->readAll();
|
||||||
|
|
||||||
|
if (data.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto roomid = reply->property("userid").toString();
|
||||||
|
|
||||||
|
QImage img;
|
||||||
|
img.loadFromData(data);
|
||||||
|
|
||||||
|
emit userAvatarRetrieved(roomid, img);
|
||||||
|
}
|
||||||
void MatrixClient::onGetOwnAvatarResponse(QNetworkReply *reply)
|
void MatrixClient::onGetOwnAvatarResponse(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
@ -392,6 +415,9 @@ void MatrixClient::onResponse(QNetworkReply *reply)
|
|||||||
case Endpoint::RoomAvatar:
|
case Endpoint::RoomAvatar:
|
||||||
onRoomAvatarResponse(reply);
|
onRoomAvatarResponse(reply);
|
||||||
break;
|
break;
|
||||||
|
case Endpoint::UserAvatar:
|
||||||
|
onUserAvatarResponse(reply);
|
||||||
|
break;
|
||||||
case Endpoint::GetOwnAvatar:
|
case Endpoint::GetOwnAvatar:
|
||||||
onGetOwnAvatarResponse(reply);
|
onGetOwnAvatarResponse(reply);
|
||||||
break;
|
break;
|
||||||
@ -591,6 +617,32 @@ void MatrixClient::fetchRoomAvatar(const QString &roomid, const QUrl &avatar_url
|
|||||||
reply->setProperty("endpoint", static_cast<int>(Endpoint::RoomAvatar));
|
reply->setProperty("endpoint", static_cast<int>(Endpoint::RoomAvatar));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MatrixClient::fetchUserAvatar(const QString &userId, const QUrl &avatarUrl)
|
||||||
|
{
|
||||||
|
QList<QString> url_parts = avatarUrl.toString().split("mxc://");
|
||||||
|
|
||||||
|
if (url_parts.size() != 2) {
|
||||||
|
qDebug() << "Invalid format for user avatar " << avatarUrl.toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("width", "128");
|
||||||
|
query.addQueryItem("height", "128");
|
||||||
|
query.addQueryItem("method", "crop");
|
||||||
|
|
||||||
|
QString media_url = QString("%1/_matrix/media/r0/thumbnail/%2").arg(getHomeServer().toString(), url_parts[1]);
|
||||||
|
|
||||||
|
QUrl endpoint(media_url);
|
||||||
|
endpoint.setQuery(query);
|
||||||
|
|
||||||
|
QNetworkRequest avatar_request(endpoint);
|
||||||
|
|
||||||
|
QNetworkReply *reply = get(avatar_request);
|
||||||
|
reply->setProperty("userid", userId);
|
||||||
|
reply->setProperty("endpoint", static_cast<int>(Endpoint::UserAvatar));
|
||||||
|
}
|
||||||
|
|
||||||
void MatrixClient::downloadImage(const QString &event_id, const QUrl &url)
|
void MatrixClient::downloadImage(const QString &event_id, const QUrl &url)
|
||||||
{
|
{
|
||||||
QNetworkRequest image_request(url);
|
QNetworkRequest image_request(url);
|
||||||
|
@ -35,7 +35,6 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
|
|
||||||
back_button_ = new FlatButton(this);
|
back_button_ = new FlatButton(this);
|
||||||
back_button_->setMinimumSize(QSize(30, 30));
|
back_button_->setMinimumSize(QSize(30, 30));
|
||||||
back_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
|
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||||
@ -109,7 +108,6 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
|
|||||||
register_button_->setBackgroundColor(QColor("#333333"));
|
register_button_->setBackgroundColor(QColor("#333333"));
|
||||||
register_button_->setForegroundColor(QColor("white"));
|
register_button_->setForegroundColor(QColor("white"));
|
||||||
register_button_->setMinimumSize(350, 65);
|
register_button_->setMinimumSize(350, 65);
|
||||||
register_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
register_button_->setFontSize(17);
|
register_button_->setFontSize(17);
|
||||||
register_button_->setCornerRadius(3);
|
register_button_->setCornerRadius(3);
|
||||||
|
|
||||||
|
@ -24,10 +24,14 @@
|
|||||||
#include "RoomState.h"
|
#include "RoomState.h"
|
||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
|
|
||||||
RoomInfoListItem::RoomInfoListItem(RoomState state, QString room_id, QWidget *parent)
|
RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
|
||||||
|
RoomState state,
|
||||||
|
QString room_id,
|
||||||
|
QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, state_(state)
|
, state_(state)
|
||||||
, roomId_(room_id)
|
, roomId_(room_id)
|
||||||
|
, roomSettings_{settings}
|
||||||
, isPressed_(false)
|
, isPressed_(false)
|
||||||
, maxHeight_(IconSize + 2 * Padding)
|
, maxHeight_(IconSize + 2 * Padding)
|
||||||
, unreadMsgCount_(0)
|
, unreadMsgCount_(0)
|
||||||
@ -44,6 +48,24 @@ RoomInfoListItem::RoomInfoListItem(RoomState state, QString room_id, QWidget *pa
|
|||||||
ripple_overlay_ = new RippleOverlay(this);
|
ripple_overlay_ = new RippleOverlay(this);
|
||||||
ripple_overlay_->setClipPath(path);
|
ripple_overlay_->setClipPath(path);
|
||||||
ripple_overlay_->setClipping(true);
|
ripple_overlay_->setClipping(true);
|
||||||
|
|
||||||
|
menu_ = new Menu(this);
|
||||||
|
|
||||||
|
toggleNotifications_ = new QAction(notificationText(), this);
|
||||||
|
|
||||||
|
connect(toggleNotifications_, &QAction::triggered, this, [=]() {
|
||||||
|
roomSettings_->toggleNotifications();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu_->addAction(toggleNotifications_);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RoomInfoListItem::notificationText()
|
||||||
|
{
|
||||||
|
if (roomSettings_.isNull() || roomSettings_->isNotificationsEnabled())
|
||||||
|
return QString(tr("Disable notifications"));
|
||||||
|
|
||||||
|
return tr("Enable notifications");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomInfoListItem::paintEvent(QPaintEvent *event)
|
void RoomInfoListItem::paintEvent(QPaintEvent *event)
|
||||||
@ -193,8 +215,21 @@ void RoomInfoListItem::setState(const RoomState &new_state)
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RoomInfoListItem::contextMenuEvent(QContextMenuEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
|
||||||
|
toggleNotifications_->setText(notificationText());
|
||||||
|
menu_->popup(event->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
void RoomInfoListItem::mousePressEvent(QMouseEvent *event)
|
void RoomInfoListItem::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
if (event->buttons() == Qt::RightButton) {
|
||||||
|
QWidget::mousePressEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emit clicked(roomId_);
|
emit clicked(roomId_);
|
||||||
|
|
||||||
setPressedState(true);
|
setPressedState(true);
|
||||||
|
@ -92,10 +92,17 @@ void RoomList::calculateUnreadMessageCount()
|
|||||||
emit totalUnreadMessageCountUpdated(total_unread_msgs);
|
emit totalUnreadMessageCountUpdated(total_unread_msgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomList::setInitialRooms(const QMap<QString, RoomState> &states)
|
void RoomList::setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
|
||||||
|
const QMap<QString, RoomState> &states)
|
||||||
{
|
{
|
||||||
rooms_.clear();
|
rooms_.clear();
|
||||||
|
|
||||||
|
if (settings.size() != states.size()) {
|
||||||
|
qWarning() << "Initializing room list";
|
||||||
|
qWarning() << "Different number of room states and room settings";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto it = states.constBegin(); it != states.constEnd(); it++) {
|
for (auto it = states.constBegin(); it != states.constEnd(); it++) {
|
||||||
auto room_id = it.key();
|
auto room_id = it.key();
|
||||||
auto state = it.value();
|
auto state = it.value();
|
||||||
@ -103,7 +110,7 @@ void RoomList::setInitialRooms(const QMap<QString, RoomState> &states)
|
|||||||
if (!state.getAvatar().toString().isEmpty())
|
if (!state.getAvatar().toString().isEmpty())
|
||||||
client_->fetchRoomAvatar(room_id, state.getAvatar());
|
client_->fetchRoomAvatar(room_id, state.getAvatar());
|
||||||
|
|
||||||
RoomInfoListItem *room_item = new RoomInfoListItem(state, room_id, scrollArea_);
|
RoomInfoListItem *room_item = new RoomInfoListItem(settings[room_id], state, room_id, scrollArea_);
|
||||||
connect(room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
|
connect(room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
|
||||||
|
|
||||||
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
FilteredTextEdit::FilteredTextEdit(QWidget *parent)
|
FilteredTextEdit::FilteredTextEdit(QWidget *parent)
|
||||||
: QTextEdit(parent)
|
: QTextEdit(parent)
|
||||||
{
|
{
|
||||||
|
setAcceptRichText(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilteredTextEdit::keyPressEvent(QKeyEvent *event)
|
void FilteredTextEdit::keyPressEvent(QKeyEvent *event)
|
||||||
@ -49,7 +50,6 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
|||||||
top_layout_->setMargin(0);
|
top_layout_->setMargin(0);
|
||||||
|
|
||||||
send_file_button_ = new FlatButton(this);
|
send_file_button_ = new FlatButton(this);
|
||||||
send_file_button_->setCursor(Qt::PointingHandCursor);
|
|
||||||
|
|
||||||
QIcon send_file_icon;
|
QIcon send_file_icon;
|
||||||
send_file_icon.addFile(":/icons/icons/clip-dark.png", QSize(), QIcon::Normal, QIcon::Off);
|
send_file_icon.addFile(":/icons/icons/clip-dark.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||||
@ -63,7 +63,6 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
|||||||
input_->setStyleSheet("color: #333333; font-size: 13px; border-radius: 0; padding-top: 10px;");
|
input_->setStyleSheet("color: #333333; font-size: 13px; border-radius: 0; padding-top: 10px;");
|
||||||
|
|
||||||
send_message_button_ = new FlatButton(this);
|
send_message_button_ = new FlatButton(this);
|
||||||
send_message_button_->setCursor(Qt::PointingHandCursor);
|
|
||||||
send_message_button_->setForegroundColor(QColor("#acc7dc"));
|
send_message_button_->setForegroundColor(QColor("#acc7dc"));
|
||||||
|
|
||||||
QIcon send_message_icon;
|
QIcon send_message_icon;
|
||||||
@ -72,7 +71,6 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
|||||||
send_message_button_->setIconSize(QSize(24, 24));
|
send_message_button_->setIconSize(QSize(24, 24));
|
||||||
|
|
||||||
emoji_button_ = new EmojiPickButton(this);
|
emoji_button_ = new EmojiPickButton(this);
|
||||||
emoji_button_->setCursor(Qt::PointingHandCursor);
|
|
||||||
emoji_button_->setForegroundColor(QColor("#acc7dc"));
|
emoji_button_->setForegroundColor(QColor("#acc7dc"));
|
||||||
|
|
||||||
QIcon emoji_icon;
|
QIcon emoji_icon;
|
||||||
|
@ -17,8 +17,10 @@
|
|||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QFontDatabase>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
|
||||||
|
#include "AvatarProvider.h"
|
||||||
#include "ImageItem.h"
|
#include "ImageItem.h"
|
||||||
#include "TimelineItem.h"
|
#include "TimelineItem.h"
|
||||||
#include "TimelineViewManager.h"
|
#include "TimelineViewManager.h"
|
||||||
@ -29,65 +31,119 @@ static const QString URL_HTML = "<a href=\"\\1\" style=\"color: #333333\">\\1</a
|
|||||||
namespace events = matrix::events;
|
namespace events = matrix::events;
|
||||||
namespace msgs = matrix::events::messages;
|
namespace msgs = matrix::events::messages;
|
||||||
|
|
||||||
|
void TimelineItem::init()
|
||||||
|
{
|
||||||
|
userAvatar_ = nullptr;
|
||||||
|
timestamp_ = nullptr;
|
||||||
|
userName_ = nullptr;
|
||||||
|
body_ = nullptr;
|
||||||
|
|
||||||
|
QFontDatabase db;
|
||||||
|
|
||||||
|
bodyFont_ = db.font("Open Sans", "Regular", 10);
|
||||||
|
usernameFont_ = db.font("Open Sans", "Bold", 10);
|
||||||
|
timestampFont_ = db.font("Open Sans", "Regular", 7);
|
||||||
|
|
||||||
|
topLayout_ = new QHBoxLayout(this);
|
||||||
|
sideLayout_ = new QVBoxLayout();
|
||||||
|
mainLayout_ = new QVBoxLayout();
|
||||||
|
headerLayout_ = new QHBoxLayout();
|
||||||
|
|
||||||
|
topLayout_->setContentsMargins(7, 0, 0, 0);
|
||||||
|
topLayout_->setSpacing(9);
|
||||||
|
|
||||||
|
topLayout_->addLayout(sideLayout_);
|
||||||
|
topLayout_->addLayout(mainLayout_, 1);
|
||||||
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(const QString &userid, const QString &color, QString body, QWidget *parent)
|
TimelineItem::TimelineItem(const QString &userid, const QString &color, QString body, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
|
auto displayName = TimelineViewManager::displayName(userid);
|
||||||
|
|
||||||
generateTimestamp(QDateTime::currentDateTime());
|
generateTimestamp(QDateTime::currentDateTime());
|
||||||
generateBody(TimelineViewManager::displayName(userid), color, body);
|
generateBody(displayName, color, body);
|
||||||
setupLayout();
|
|
||||||
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
|
mainLayout_->addLayout(headerLayout_);
|
||||||
|
mainLayout_->addWidget(body_);
|
||||||
|
mainLayout_->setMargin(0);
|
||||||
|
mainLayout_->setSpacing(0);
|
||||||
|
|
||||||
|
AvatarProvider::resolve(userid, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(QString body, QWidget *parent)
|
TimelineItem::TimelineItem(QString body, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
|
|
||||||
generateTimestamp(QDateTime::currentDateTime());
|
generateTimestamp(QDateTime::currentDateTime());
|
||||||
generateBody(body);
|
generateBody(body);
|
||||||
setupLayout();
|
|
||||||
|
setupSimpleLayout();
|
||||||
|
|
||||||
|
mainLayout_->addWidget(body_);
|
||||||
|
mainLayout_->setMargin(0);
|
||||||
|
mainLayout_->setSpacing(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, const QString &color, QWidget *parent)
|
TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, const QString &color, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||||
|
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||||
|
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
generateBody(TimelineViewManager::displayName(event.sender()), color, "");
|
generateBody(displayName, color, "");
|
||||||
|
|
||||||
top_layout_ = new QHBoxLayout();
|
setupAvatarLayout(displayName);
|
||||||
top_layout_->setMargin(0);
|
|
||||||
top_layout_->addWidget(time_label_);
|
|
||||||
|
|
||||||
auto right_layout = new QVBoxLayout();
|
auto imageLayout = new QHBoxLayout();
|
||||||
right_layout->addWidget(content_label_);
|
imageLayout->addWidget(image);
|
||||||
right_layout->addWidget(image);
|
imageLayout->addStretch(1);
|
||||||
|
|
||||||
top_layout_->addLayout(right_layout);
|
mainLayout_->addLayout(headerLayout_);
|
||||||
top_layout_->addStretch(1);
|
mainLayout_->addLayout(imageLayout);
|
||||||
|
mainLayout_->setContentsMargins(0, 4, 0, 0);
|
||||||
|
mainLayout_->setSpacing(0);
|
||||||
|
|
||||||
setLayout(top_layout_);
|
AvatarProvider::resolve(event.sender(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, QWidget *parent)
|
TimelineItem::TimelineItem(ImageItem *image, const events::MessageEvent<msgs::Image> &event, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||||
generateTimestamp(timestamp);
|
generateTimestamp(timestamp);
|
||||||
|
|
||||||
top_layout_ = new QHBoxLayout();
|
setupSimpleLayout();
|
||||||
top_layout_->setMargin(0);
|
|
||||||
top_layout_->addWidget(time_label_);
|
|
||||||
top_layout_->addWidget(image, 1);
|
|
||||||
top_layout_->addStretch(1);
|
|
||||||
|
|
||||||
setLayout(top_layout_);
|
auto imageLayout = new QHBoxLayout();
|
||||||
|
imageLayout->setMargin(0);
|
||||||
|
imageLayout->addWidget(image);
|
||||||
|
imageLayout->addStretch(1);
|
||||||
|
|
||||||
|
mainLayout_->addLayout(imageLayout);
|
||||||
|
mainLayout_->setContentsMargins(0, 4, 0, 0);
|
||||||
|
mainLayout_->setSpacing(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool with_sender, const QString &color, QWidget *parent)
|
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool with_sender, const QString &color, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
auto body = event.content().body().trimmed().toHtmlEscaped();
|
auto body = event.content().body().trimmed().toHtmlEscaped();
|
||||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||||
|
|
||||||
@ -96,17 +152,34 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Notice> &event, bool
|
|||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
body = "<i style=\"color: #565E5E\">" + body + "</i>";
|
body = "<i style=\"color: #565E5E\">" + body + "</i>";
|
||||||
|
|
||||||
if (with_sender)
|
if (with_sender) {
|
||||||
generateBody(TimelineViewManager::displayName(event.sender()), color, body);
|
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||||
else
|
|
||||||
|
generateBody(displayName, color, body);
|
||||||
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
|
mainLayout_->addLayout(headerLayout_);
|
||||||
|
mainLayout_->addWidget(body_);
|
||||||
|
mainLayout_->setMargin(0);
|
||||||
|
mainLayout_->setSpacing(0);
|
||||||
|
|
||||||
|
AvatarProvider::resolve(event.sender(), this);
|
||||||
|
} else {
|
||||||
generateBody(body);
|
generateBody(body);
|
||||||
|
|
||||||
setupLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
|
mainLayout_->addWidget(body_);
|
||||||
|
mainLayout_->setMargin(0);
|
||||||
|
mainLayout_->setSpacing(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool with_sender, const QString &color, QWidget *parent)
|
TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool with_sender, const QString &color, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
auto body = event.content().body().trimmed().toHtmlEscaped();
|
auto body = event.content().body().trimmed().toHtmlEscaped();
|
||||||
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
auto timestamp = QDateTime::fromMSecsSinceEpoch(event.timestamp());
|
||||||
|
|
||||||
@ -114,34 +187,45 @@ TimelineItem::TimelineItem(const events::MessageEvent<msgs::Text> &event, bool w
|
|||||||
|
|
||||||
body.replace(URL_REGEX, URL_HTML);
|
body.replace(URL_REGEX, URL_HTML);
|
||||||
|
|
||||||
if (with_sender)
|
if (with_sender) {
|
||||||
generateBody(TimelineViewManager::displayName(event.sender()), color, body);
|
auto displayName = TimelineViewManager::displayName(event.sender());
|
||||||
else
|
generateBody(displayName, color, body);
|
||||||
|
|
||||||
|
setupAvatarLayout(displayName);
|
||||||
|
|
||||||
|
mainLayout_->addLayout(headerLayout_);
|
||||||
|
mainLayout_->addWidget(body_);
|
||||||
|
mainLayout_->setMargin(0);
|
||||||
|
mainLayout_->setSpacing(0);
|
||||||
|
|
||||||
|
AvatarProvider::resolve(event.sender(), this);
|
||||||
|
} else {
|
||||||
generateBody(body);
|
generateBody(body);
|
||||||
|
|
||||||
setupLayout();
|
setupSimpleLayout();
|
||||||
|
|
||||||
|
mainLayout_->addWidget(body_);
|
||||||
|
mainLayout_->setMargin(0);
|
||||||
|
mainLayout_->setSpacing(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only the body is displayed.
|
||||||
void TimelineItem::generateBody(const QString &body)
|
void TimelineItem::generateBody(const QString &body)
|
||||||
{
|
{
|
||||||
content_label_ = new QLabel(this);
|
QString content("<span style=\"color: #171919;\">%1</span>");
|
||||||
content_label_->setWordWrap(true);
|
|
||||||
content_label_->setAlignment(Qt::AlignTop);
|
body_ = new QLabel(this);
|
||||||
content_label_->setStyleSheet("margin: 0;");
|
body_->setWordWrap(true);
|
||||||
QString content(
|
body_->setFont(bodyFont_);
|
||||||
"<html>"
|
body_->setText(content.arg(replaceEmoji(body)));
|
||||||
"<head/>"
|
body_->setAlignment(Qt::AlignTop);
|
||||||
"<body>"
|
|
||||||
" <span style=\"font-size: 10pt; color: #171919;\">"
|
body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
|
||||||
" %1"
|
body_->setOpenExternalLinks(true);
|
||||||
" </span>"
|
|
||||||
"</body>"
|
|
||||||
"</html>");
|
|
||||||
content_label_->setText(content.arg(replaceEmoji(body)));
|
|
||||||
content_label_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
|
|
||||||
content_label_->setOpenExternalLinks(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The username/timestamp is displayed along with the message body.
|
||||||
void TimelineItem::generateBody(const QString &userid, const QString &color, const QString &body)
|
void TimelineItem::generateBody(const QString &userid, const QString &color, const QString &body)
|
||||||
{
|
{
|
||||||
auto sender = userid;
|
auto sender = userid;
|
||||||
@ -150,64 +234,35 @@ void TimelineItem::generateBody(const QString &userid, const QString &color, con
|
|||||||
if (userid.split(":")[0].split("@").size() > 1)
|
if (userid.split(":")[0].split("@").size() > 1)
|
||||||
sender = userid.split(":")[0].split("@")[1];
|
sender = userid.split(":")[0].split("@")[1];
|
||||||
|
|
||||||
content_label_ = new QLabel(this);
|
QString userContent("<span style=\"color: %1\"> %2 </span>");
|
||||||
content_label_->setWordWrap(true);
|
QString bodyContent("<span style=\"color: #171717;\"> %1 </span>");
|
||||||
content_label_->setAlignment(Qt::AlignTop);
|
|
||||||
content_label_->setStyleSheet("margin: 0;");
|
userName_ = new QLabel(this);
|
||||||
QString content(
|
userName_->setFont(usernameFont_);
|
||||||
"<html>"
|
userName_->setText(userContent.arg(color).arg(sender));
|
||||||
"<head/>"
|
userName_->setAlignment(Qt::AlignTop);
|
||||||
"<body>"
|
|
||||||
" <span style=\"font-size: 10pt; font-weight: 600; color: %1\">"
|
if (body.isEmpty())
|
||||||
" %2"
|
return;
|
||||||
" </span>"
|
|
||||||
" <span style=\"font-size: 10pt; color: #171919;\">"
|
body_ = new QLabel(this);
|
||||||
" %3"
|
body_->setFont(bodyFont_);
|
||||||
" </span>"
|
body_->setWordWrap(true);
|
||||||
"</body>"
|
body_->setAlignment(Qt::AlignTop);
|
||||||
"</html>");
|
body_->setText(bodyContent.arg(replaceEmoji(body)));
|
||||||
content_label_->setText(content.arg(color).arg(sender).arg(replaceEmoji(body)));
|
body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
|
||||||
content_label_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
|
body_->setOpenExternalLinks(true);
|
||||||
content_label_->setOpenExternalLinks(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineItem::generateTimestamp(const QDateTime &time)
|
void TimelineItem::generateTimestamp(const QDateTime &time)
|
||||||
{
|
{
|
||||||
auto local_time = time.toString("HH:mm");
|
QString msg("<span style=\"color: #5d6565;\"> %1 </span>");
|
||||||
|
|
||||||
time_label_ = new QLabel(this);
|
timestamp_ = new QLabel(this);
|
||||||
QString msg(
|
timestamp_->setFont(timestampFont_);
|
||||||
"<html>"
|
timestamp_->setText(msg.arg(time.toString("HH:mm")));
|
||||||
"<head/>"
|
timestamp_->setAlignment(Qt::AlignTop);
|
||||||
"<body>"
|
timestamp_->setStyleSheet("margin-top: 2px;");
|
||||||
" <span style=\"font-size: 7pt; color: #5d6565;\">"
|
|
||||||
" %1"
|
|
||||||
" </span>"
|
|
||||||
"</body>"
|
|
||||||
"</html>");
|
|
||||||
time_label_->setText(msg.arg(local_time));
|
|
||||||
time_label_->setStyleSheet("margin-left: 7px; margin-right: 7px; margin-top: 0;");
|
|
||||||
time_label_->setAlignment(Qt::AlignTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimelineItem::setupLayout()
|
|
||||||
{
|
|
||||||
if (time_label_ == nullptr) {
|
|
||||||
qWarning() << "TimelineItem: Time label is not initialized";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content_label_ == nullptr) {
|
|
||||||
qWarning() << "TimelineItem: Content label is not initialized";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
top_layout_ = new QHBoxLayout();
|
|
||||||
top_layout_->setMargin(0);
|
|
||||||
top_layout_->addWidget(time_label_);
|
|
||||||
top_layout_->addWidget(content_label_, 1);
|
|
||||||
|
|
||||||
setLayout(top_layout_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TimelineItem::replaceEmoji(const QString &body)
|
QString TimelineItem::replaceEmoji(const QString &body)
|
||||||
@ -227,6 +282,46 @@ QString TimelineItem::replaceEmoji(const QString &body)
|
|||||||
return fmtBody;
|
return fmtBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TimelineItem::setupAvatarLayout(const QString &userName)
|
||||||
|
{
|
||||||
|
topLayout_->setContentsMargins(7, 6, 0, 0);
|
||||||
|
|
||||||
|
userAvatar_ = new Avatar(this);
|
||||||
|
userAvatar_->setLetter(QChar(userName[0]).toUpper());
|
||||||
|
userAvatar_->setBackgroundColor(QColor("#eee"));
|
||||||
|
userAvatar_->setTextColor(QColor("black"));
|
||||||
|
userAvatar_->setSize(32);
|
||||||
|
|
||||||
|
// TODO: The provided user name should be a UserId class
|
||||||
|
if (userName[0] == '@' && userName.size() > 1)
|
||||||
|
userAvatar_->setLetter(QChar(userName[1]).toUpper());
|
||||||
|
|
||||||
|
sideLayout_->addWidget(userAvatar_);
|
||||||
|
sideLayout_->addStretch(1);
|
||||||
|
sideLayout_->setMargin(0);
|
||||||
|
sideLayout_->setSpacing(0);
|
||||||
|
|
||||||
|
headerLayout_->addWidget(userName_);
|
||||||
|
headerLayout_->addWidget(timestamp_, 1);
|
||||||
|
headerLayout_->setMargin(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineItem::setupSimpleLayout()
|
||||||
|
{
|
||||||
|
sideLayout_->addWidget(timestamp_);
|
||||||
|
sideLayout_->addStretch(1);
|
||||||
|
|
||||||
|
topLayout_->setContentsMargins(9, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineItem::setUserAvatar(const QImage &avatar)
|
||||||
|
{
|
||||||
|
if (userAvatar_ == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
userAvatar_->setImage(avatar);
|
||||||
|
}
|
||||||
|
|
||||||
TimelineItem::~TimelineItem()
|
TimelineItem::~TimelineItem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,9 @@ int TimelineView::addEvents(const Timeline &timeline)
|
|||||||
{
|
{
|
||||||
int message_count = 0;
|
int message_count = 0;
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
QString localUser = settings.value("auth/user_id").toString();
|
||||||
|
|
||||||
if (isInitialSync) {
|
if (isInitialSync) {
|
||||||
prev_batch_token_ = timeline.previousBatch();
|
prev_batch_token_ = timeline.previousBatch();
|
||||||
isInitialSync = false;
|
isInitialSync = false;
|
||||||
@ -220,10 +223,13 @@ int TimelineView::addEvents(const Timeline &timeline)
|
|||||||
|
|
||||||
for (const auto &event : timeline.events()) {
|
for (const auto &event : timeline.events()) {
|
||||||
TimelineItem *item = parseMessageEvent(event.toObject(), TimelineDirection::Bottom);
|
TimelineItem *item = parseMessageEvent(event.toObject(), TimelineDirection::Bottom);
|
||||||
|
auto sender = event.toObject().value("sender").toString();
|
||||||
|
|
||||||
if (item != nullptr) {
|
if (item != nullptr) {
|
||||||
message_count += 1;
|
|
||||||
addTimelineItem(item, TimelineDirection::Bottom);
|
addTimelineItem(item, TimelineDirection::Bottom);
|
||||||
|
|
||||||
|
if (sender != localUser)
|
||||||
|
message_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
TopRoomBar::TopRoomBar(QWidget *parent)
|
TopRoomBar::TopRoomBar(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
, buttonSize_{32}
|
||||||
{
|
{
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
setMinimumSize(QSize(0, 65));
|
setMinimumSize(QSize(0, 65));
|
||||||
@ -28,7 +29,7 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||||||
|
|
||||||
top_layout_ = new QHBoxLayout();
|
top_layout_ = new QHBoxLayout();
|
||||||
top_layout_->setSpacing(10);
|
top_layout_->setSpacing(10);
|
||||||
top_layout_->setContentsMargins(10, 10, 0, 10);
|
top_layout_->setMargin(10);
|
||||||
|
|
||||||
avatar_ = new Avatar(this);
|
avatar_ = new Avatar(this);
|
||||||
avatar_->setLetter(QChar('?'));
|
avatar_->setLetter(QChar('?'));
|
||||||
@ -49,31 +50,40 @@ TopRoomBar::TopRoomBar(QWidget *parent)
|
|||||||
text_layout_->addWidget(name_label_);
|
text_layout_->addWidget(name_label_);
|
||||||
text_layout_->addWidget(topic_label_);
|
text_layout_->addWidget(topic_label_);
|
||||||
|
|
||||||
settings_button_ = new FlatButton(this);
|
settingsBtn_ = new FlatButton(this);
|
||||||
settings_button_->setForegroundColor(QColor("#acc7dc"));
|
settingsBtn_->setForegroundColor(QColor("#acc7dc"));
|
||||||
settings_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
settingsBtn_->setFixedSize(buttonSize_, buttonSize_);
|
||||||
settings_button_->setStyleSheet("width: 30px; height: 30px;");
|
settingsBtn_->setCornerRadius(buttonSize_ / 2);
|
||||||
|
|
||||||
QIcon settings_icon;
|
QIcon settings_icon;
|
||||||
settings_icon.addFile(":/icons/icons/cog.png", QSize(), QIcon::Normal, QIcon::Off);
|
settings_icon.addFile(":/icons/icons/vertical-ellipsis.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||||
settings_button_->setIcon(settings_icon);
|
settingsBtn_->setIcon(settings_icon);
|
||||||
settings_button_->setIconSize(QSize(16, 16));
|
settingsBtn_->setIconSize(QSize(buttonSize_ / 2, buttonSize_ / 2));
|
||||||
|
|
||||||
search_button_ = new FlatButton(this);
|
|
||||||
search_button_->setForegroundColor(QColor("#acc7dc"));
|
|
||||||
search_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
search_button_->setStyleSheet("width: 30px; height: 30px;");
|
|
||||||
|
|
||||||
QIcon search_icon;
|
|
||||||
search_icon.addFile(":/icons/icons/search.png", QSize(), QIcon::Normal, QIcon::Off);
|
|
||||||
search_button_->setIcon(search_icon);
|
|
||||||
search_button_->setIconSize(QSize(16, 16));
|
|
||||||
|
|
||||||
top_layout_->addWidget(avatar_);
|
top_layout_->addWidget(avatar_);
|
||||||
top_layout_->addLayout(text_layout_);
|
top_layout_->addLayout(text_layout_);
|
||||||
top_layout_->addStretch(1);
|
top_layout_->addStretch(1);
|
||||||
top_layout_->addWidget(search_button_);
|
top_layout_->addWidget(settingsBtn_);
|
||||||
top_layout_->addWidget(settings_button_);
|
|
||||||
|
menu_ = new Menu(this);
|
||||||
|
|
||||||
|
toggleNotifications_ = new QAction(tr("Disable notifications"), this);
|
||||||
|
connect(toggleNotifications_, &QAction::triggered, this, [=]() {
|
||||||
|
roomSettings_->toggleNotifications();
|
||||||
|
});
|
||||||
|
|
||||||
|
menu_->addAction(toggleNotifications_);
|
||||||
|
|
||||||
|
connect(settingsBtn_, &QPushButton::clicked, this, [=]() {
|
||||||
|
if (roomSettings_->isNotificationsEnabled())
|
||||||
|
toggleNotifications_->setText(tr("Disable notifications"));
|
||||||
|
else
|
||||||
|
toggleNotifications_->setText(tr("Enable notifications"));
|
||||||
|
|
||||||
|
auto pos = mapToGlobal(settingsBtn_->pos());
|
||||||
|
menu_->popup(QPoint(pos.x() + buttonSize_ - menu_->sizeHint().width(),
|
||||||
|
pos.y() + buttonSize_));
|
||||||
|
});
|
||||||
|
|
||||||
setLayout(top_layout_);
|
setLayout(top_layout_);
|
||||||
}
|
}
|
||||||
@ -106,6 +116,11 @@ void TopRoomBar::paintEvent(QPaintEvent *event)
|
|||||||
style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
|
style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TopRoomBar::setRoomSettings(QSharedPointer<RoomSettings> settings)
|
||||||
|
{
|
||||||
|
roomSettings_ = settings;
|
||||||
|
}
|
||||||
|
|
||||||
TopRoomBar::~TopRoomBar()
|
TopRoomBar::~TopRoomBar()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include "UserInfoWidget.h"
|
#include "UserInfoWidget.h"
|
||||||
|
|
||||||
UserInfoWidget::UserInfoWidget(QWidget *parent)
|
UserInfoWidget::UserInfoWidget(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, display_name_("User")
|
, display_name_("User")
|
||||||
, user_id_("@user:homeserver.org")
|
, user_id_("@user:homeserver.org")
|
||||||
|
, logoutModal_{nullptr}
|
||||||
|
, logoutDialog_{nullptr}
|
||||||
|
, logoutButtonSize_{32}
|
||||||
{
|
{
|
||||||
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||||
setSizePolicy(sizePolicy);
|
setSizePolicy(sizePolicy);
|
||||||
@ -72,19 +77,46 @@ UserInfoWidget::UserInfoWidget(QWidget *parent)
|
|||||||
|
|
||||||
logoutButton_ = new FlatButton(this);
|
logoutButton_ = new FlatButton(this);
|
||||||
logoutButton_->setForegroundColor(QColor("#555459"));
|
logoutButton_->setForegroundColor(QColor("#555459"));
|
||||||
logoutButton_->setCursor(QCursor(Qt::PointingHandCursor));
|
logoutButton_->setFixedSize(logoutButtonSize_, logoutButtonSize_);
|
||||||
|
logoutButton_->setCornerRadius(logoutButtonSize_ / 2);
|
||||||
|
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
icon.addFile(":/icons/icons/power-button-off.png", QSize(), QIcon::Normal, QIcon::Off);
|
icon.addFile(":/icons/icons/power-button-off.png", QSize(), QIcon::Normal, QIcon::Off);
|
||||||
|
|
||||||
logoutButton_->setIcon(icon);
|
logoutButton_->setIcon(icon);
|
||||||
logoutButton_->setIconSize(QSize(16, 16));
|
logoutButton_->setIconSize(QSize(logoutButtonSize_ / 2, logoutButtonSize_ / 2));
|
||||||
|
|
||||||
buttonLayout_->addWidget(logoutButton_);
|
buttonLayout_->addWidget(logoutButton_);
|
||||||
|
|
||||||
topLayout_->addLayout(buttonLayout_);
|
topLayout_->addLayout(buttonLayout_);
|
||||||
|
|
||||||
connect(logoutButton_, SIGNAL(clicked()), this, SIGNAL(logout()));
|
// Show the confirmation dialog.
|
||||||
|
connect(logoutButton_, &QPushButton::clicked, this, [=]() {
|
||||||
|
if (logoutDialog_ == nullptr) {
|
||||||
|
logoutDialog_ = new LogoutDialog(this);
|
||||||
|
connect(logoutDialog_, SIGNAL(closing(bool)), this, SLOT(closeLogoutDialog(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logoutModal_ == nullptr) {
|
||||||
|
logoutModal_ = new OverlayModal(MainWindow::instance(), logoutDialog_);
|
||||||
|
logoutModal_->setDuration(100);
|
||||||
|
logoutModal_->setColor(QColor(55, 55, 55, 170));
|
||||||
|
}
|
||||||
|
|
||||||
|
logoutModal_->fadeIn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserInfoWidget::closeLogoutDialog(bool isLoggingOut)
|
||||||
|
{
|
||||||
|
logoutModal_->fadeOut();
|
||||||
|
|
||||||
|
if (isLoggingOut) {
|
||||||
|
// Waiting for the modal to fade out.
|
||||||
|
QTimer::singleShot(100, this, [=]() {
|
||||||
|
emit logout();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UserInfoWidget::~UserInfoWidget()
|
UserInfoWidget::~UserInfoWidget()
|
||||||
|
@ -61,7 +61,6 @@ WelcomePage::WelcomePage(QWidget *parent)
|
|||||||
register_button_->setBackgroundColor(QColor("#333333"));
|
register_button_->setBackgroundColor(QColor("#333333"));
|
||||||
register_button_->setForegroundColor(QColor("white"));
|
register_button_->setForegroundColor(QColor("white"));
|
||||||
register_button_->setMinimumSize(240, 60);
|
register_button_->setMinimumSize(240, 60);
|
||||||
register_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
register_button_->setFontSize(14);
|
register_button_->setFontSize(14);
|
||||||
register_button_->setCornerRadius(3);
|
register_button_->setCornerRadius(3);
|
||||||
|
|
||||||
@ -69,7 +68,6 @@ WelcomePage::WelcomePage(QWidget *parent)
|
|||||||
login_button_->setBackgroundColor(QColor("#333333"));
|
login_button_->setBackgroundColor(QColor("#333333"));
|
||||||
login_button_->setForegroundColor(QColor("white"));
|
login_button_->setForegroundColor(QColor("white"));
|
||||||
login_button_->setMinimumSize(240, 60);
|
login_button_->setMinimumSize(240, 60);
|
||||||
login_button_->setCursor(QCursor(Qt::PointingHandCursor));
|
|
||||||
login_button_->setFontSize(14);
|
login_button_->setFontSize(14);
|
||||||
login_button_->setCornerRadius(3);
|
login_button_->setCornerRadius(3);
|
||||||
|
|
||||||
|
@ -36,9 +36,7 @@ int main(int argc, char *argv[])
|
|||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Regular.ttf");
|
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Regular.ttf");
|
||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Italic.ttf");
|
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Italic.ttf");
|
||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Bold.ttf");
|
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Bold.ttf");
|
||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-BoldItalic.ttf");
|
|
||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Semibold.ttf");
|
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-Semibold.ttf");
|
||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/OpenSans/OpenSans-SemiboldItalic.ttf");
|
|
||||||
QFontDatabase::addApplicationFont(":/fonts/fonts/EmojiOne/emojione-android.ttf");
|
QFontDatabase::addApplicationFont(":/fonts/fonts/EmojiOne/emojione-android.ttf");
|
||||||
|
|
||||||
app.setWindowIcon(QIcon(":/logos/nheko.png"));
|
app.setWindowIcon(QIcon(":/logos/nheko.png"));
|
||||||
|
@ -29,6 +29,7 @@ void FlatButton::init()
|
|||||||
setStyle(&ThemeManager::instance());
|
setStyle(&ThemeManager::instance());
|
||||||
setAttribute(Qt::WA_Hover);
|
setAttribute(Qt::WA_Hover);
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
setCursor(QCursor(Qt::PointingHandCursor));
|
||||||
|
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
path.addRoundedRect(rect(), corner_radius_, corner_radius_);
|
path.addRoundedRect(rect(), corner_radius_, corner_radius_);
|
||||||
@ -336,7 +337,7 @@ void FlatButton::mousePressEvent(QMouseEvent *event)
|
|||||||
ripple->setOpacityStartValue(0.35);
|
ripple->setOpacityStartValue(0.35);
|
||||||
ripple->setColor(foregroundColor());
|
ripple->setColor(foregroundColor());
|
||||||
ripple->radiusAnimation()->setDuration(250);
|
ripple->radiusAnimation()->setDuration(250);
|
||||||
ripple->opacityAnimation()->setDuration(400);
|
ripple->opacityAnimation()->setDuration(250);
|
||||||
|
|
||||||
ripple_overlay_->addRipple(ripple);
|
ripple_overlay_->addRipple(ripple);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user