Style change again

This commit is contained in:
Konstantinos Sideris 2017-09-10 12:59:21 +03:00
parent ed36bdb037
commit 1bfe48de75
130 changed files with 6039 additions and 5940 deletions

View file

@ -27,21 +27,21 @@
class AvatarProvider : public QObject
{
Q_OBJECT
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 init(QSharedPointer<MatrixClient> client);
static void resolve(const QString &userId, TimelineItem *item);
static void setAvatarUrl(const QString &userId, const QUrl &url);
static void clear();
static void clear();
private:
static void updateAvatar(const QString &uid, const QImage &img);
static void updateAvatar(const QString &uid, const QImage &img);
static QSharedPointer<MatrixClient> client_;
static QMap<QString, QList<TimelineItem *>> toBeResolved_;
static QSharedPointer<MatrixClient> client_;
static QMap<QString, QList<TimelineItem *>> toBeResolved_;
static QMap<QString, QImage> userAvatars_;
static QMap<QString, QUrl> avatarUrls_;
static QMap<QString, QImage> userAvatars_;
static QMap<QString, QUrl> avatarUrls_;
};

View file

@ -7,24 +7,24 @@
namespace conf
{
// Global settings.
static const int fontSize = 12;
static const int emojiSize = 14;
static const int fontSize = 12;
static const int emojiSize = 14;
static const int headerFontSize = 21;
// Window geometry.
namespace window
{
static const int height = 600;
static const int width = 1066;
static const int width = 1066;
static const int minHeight = 600;
static const int minWidth = 950;
static const int minWidth = 950;
}
// Button settings.
namespace btn
{
static const int fontSize = 20;
static const int fontSize = 20;
static const int cornerRadius = 3;
}
@ -34,8 +34,8 @@ namespace roomlist
namespace fonts
{
static const int heading = 13;
static const int badge = 10;
static const int bubble = 20;
static const int badge = 10;
static const int bubble = 20;
} // namespace fonts
} // namespace roomlist
@ -44,7 +44,7 @@ namespace userInfoWidget
namespace fonts
{
static const int displayName = 16;
static const int userid = 14;
static const int userid = 14;
} // namespace fonts
} // namespace userInfoWidget
@ -52,16 +52,16 @@ namespace topRoomBar
{
namespace fonts
{
static const int roomName = 15;
static const int roomName = 15;
static const int roomDescription = 13;
} // namespace fonts
} // namespace topRoomBar
namespace timeline
{
static const int msgMargin = 11;
static const int avatarSize = 36;
static const int headerSpacing = 5;
static const int msgMargin = 11;
static const int avatarSize = 36;
static const int headerSpacing = 5;
static const int headerLeftMargin = 15;
namespace fonts

View file

@ -26,36 +26,36 @@
class DeserializationException : public std::exception
{
public:
explicit DeserializationException(const std::string &msg);
virtual const char *what() const noexcept;
explicit DeserializationException(const std::string &msg);
virtual const char *what() const noexcept;
private:
std::string msg_;
std::string msg_;
};
// JSON response structs need to implement the interface.
class Deserializable
{
public:
virtual void deserialize(const QJsonValue &)
{
}
virtual void deserialize(const QJsonObject &)
{
}
virtual void deserialize(const QJsonDocument &)
{
}
virtual ~Deserializable()
{
}
virtual void deserialize(const QJsonValue &)
{
}
virtual void deserialize(const QJsonObject &)
{
}
virtual void deserialize(const QJsonDocument &)
{
}
virtual ~Deserializable()
{
}
};
class Serializable
{
public:
virtual QJsonObject serialize() const = 0;
virtual ~Serializable()
{
}
virtual QJsonObject serialize() const = 0;
virtual ~Serializable()
{
}
};

View file

@ -29,32 +29,32 @@
class EmojiCategory : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
EmojiCategory(QString category, QList<Emoji> emoji, QWidget *parent = nullptr);
~EmojiCategory();
EmojiCategory(QString category, QList<Emoji> emoji, QWidget *parent = nullptr);
~EmojiCategory();
signals:
void emojiSelected(const QString &emoji);
void emojiSelected(const QString &emoji);
private slots:
inline void clickIndex(const QModelIndex &);
inline void clickIndex(const QModelIndex &);
private:
QVBoxLayout *mainLayout_;
QVBoxLayout *mainLayout_;
QStandardItemModel *itemModel_;
QListView *emojiListView_;
QStandardItemModel *itemModel_;
QListView *emojiListView_;
Emoji *data_;
EmojiItemDelegate *delegate_;
Emoji *data_;
EmojiItemDelegate *delegate_;
QLabel *category_;
QLabel *category_;
};
inline void
EmojiCategory::clickIndex(const QModelIndex &index)
{
emit emojiSelected(index.data(Qt::UserRole).toString());
emit emojiSelected(index.data(Qt::UserRole).toString());
}

View file

@ -25,14 +25,16 @@
class EmojiItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
Q_OBJECT
public:
explicit EmojiItemDelegate(QObject *parent = nullptr);
~EmojiItemDelegate();
explicit EmojiItemDelegate(QObject *parent = nullptr);
~EmojiItemDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
private:
Emoji *data_;
Emoji *data_;
};

View file

@ -27,38 +27,38 @@
class EmojiPanel : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
EmojiPanel(QWidget *parent = nullptr);
EmojiPanel(QWidget *parent = nullptr);
void fadeOut();
void fadeIn();
void fadeOut();
void fadeIn();
signals:
void mouseLeft();
void emojiSelected(const QString &emoji);
void mouseLeft();
void emojiSelected(const QString &emoji);
protected:
void leaveEvent(QEvent *event);
void paintEvent(QPaintEvent *event);
void leaveEvent(QEvent *event);
void paintEvent(QPaintEvent *event);
private:
void showEmojiCategory(const EmojiCategory *category);
void showEmojiCategory(const EmojiCategory *category);
QPropertyAnimation *animation_;
QGraphicsOpacityEffect *opacity_;
QPropertyAnimation *animation_;
QGraphicsOpacityEffect *opacity_;
EmojiProvider emoji_provider_;
EmojiProvider emoji_provider_;
QScrollArea *scrollArea_;
QScrollArea *scrollArea_;
int shadowMargin_;
int shadowMargin_;
// Panel dimensions.
int width_;
int height_;
// Panel dimensions.
int width_;
int height_;
int animationDuration_;
int categoryIconSize_;
int animationDuration_;
int categoryIconSize_;
};

View file

@ -25,23 +25,23 @@
class EmojiPickButton : public FlatButton
{
Q_OBJECT
Q_OBJECT
public:
explicit EmojiPickButton(QWidget *parent = nullptr);
explicit EmojiPickButton(QWidget *parent = nullptr);
signals:
void emojiSelected(const QString &emoji);
void emojiSelected(const QString &emoji);
protected:
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override;
void enterEvent(QEvent *e) override;
void leaveEvent(QEvent *e) override;
private:
// Vertical distance from panel's bottom.
int vertical_distance_ = 10;
// Vertical distance from panel's bottom.
int vertical_distance_ = 10;
// Horizontal distance from panel's bottom right corner.
int horizontal_distance_ = 70;
// Horizontal distance from panel's bottom right corner.
int horizontal_distance_ = 70;
EmojiPanel *panel_;
EmojiPanel *panel_;
};

View file

@ -22,21 +22,21 @@
#include <QMap>
struct Emoji {
// Unicode code.
QString unicode;
// Keyboard shortcut e.g :emoji:
QString shortname;
// Unicode code.
QString unicode;
// Keyboard shortcut e.g :emoji:
QString shortname;
};
class EmojiProvider
{
public:
static const QList<Emoji> people;
static const QList<Emoji> nature;
static const QList<Emoji> food;
static const QList<Emoji> activity;
static const QList<Emoji> travel;
static const QList<Emoji> objects;
static const QList<Emoji> symbols;
static const QList<Emoji> flags;
static const QList<Emoji> people;
static const QList<Emoji> nature;
static const QList<Emoji> food;
static const QList<Emoji> activity;
static const QList<Emoji> travel;
static const QList<Emoji> objects;
static const QList<Emoji> symbols;
static const QList<Emoji> flags;
};

View file

@ -26,47 +26,47 @@
#include "MatrixClient.h"
namespace events = matrix::events;
namespace msgs = matrix::events::messages;
namespace msgs = matrix::events::messages;
class ImageItem : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
ImageItem(QSharedPointer<MatrixClient> client,
const events::MessageEvent<msgs::Image> &event,
QWidget *parent = nullptr);
ImageItem(QSharedPointer<MatrixClient> client,
const events::MessageEvent<msgs::Image> &event,
QWidget *parent = nullptr);
void setImage(const QPixmap &image);
void setImage(const QPixmap &image);
QSize sizeHint() const override;
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private slots:
void imageDownloaded(const QString &event_id, const QPixmap &img);
void imageDownloaded(const QString &event_id, const QPixmap &img);
private:
void scaleImage();
void openUrl();
void scaleImage();
void openUrl();
int max_width_ = 500;
int max_height_ = 300;
int max_width_ = 500;
int max_height_ = 300;
int width_;
int height_;
int width_;
int height_;
QPixmap scaled_image_;
QPixmap image_;
QPixmap scaled_image_;
QPixmap image_;
QUrl url_;
QString text_;
QUrl url_;
QString text_;
int bottom_height_ = 30;
int bottom_height_ = 30;
events::MessageEvent<msgs::Image> event_;
events::MessageEvent<msgs::Image> event_;
QSharedPointer<MatrixClient> client_;
QSharedPointer<MatrixClient> client_;
};

View file

@ -23,24 +23,24 @@
class ImageOverlayDialog : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
ImageOverlayDialog(QPixmap image, QWidget *parent = nullptr);
ImageOverlayDialog(QPixmap image, QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
signals:
void closing();
void closing();
private:
void scaleImage(int width, int height);
void scaleImage(int width, int height);
QPixmap originalImage_;
QPixmap image_;
QPixmap originalImage_;
QPixmap image_;
QRect content_;
QRect close_button_;
QRect screen_;
QRect content_;
QRect close_button_;
QRect screen_;
};

View file

@ -23,9 +23,9 @@
class InputValidator
{
public:
// Validators for the different types of input.
static QRegExpValidator Id;
static QRegExpValidator Localpart;
static QRegExpValidator Password;
static QRegExpValidator Domain;
// Validators for the different types of input.
static QRegExpValidator Id;
static QRegExpValidator Localpart;
static QRegExpValidator Password;
static QRegExpValidator Domain;
};

View file

@ -24,60 +24,60 @@
class LoginRequest
{
public:
LoginRequest();
LoginRequest(QString username, QString password);
LoginRequest();
LoginRequest(QString username, QString password);
QByteArray serialize() noexcept;
QByteArray serialize() noexcept;
inline void setPassword(QString password);
inline void setUser(QString username);
inline void setPassword(QString password);
inline void setUser(QString username);
private:
QString user_;
QString password_;
QString user_;
QString password_;
};
inline void
LoginRequest::setPassword(QString password)
{
password_ = password;
password_ = password;
}
inline void
LoginRequest::setUser(QString username)
{
user_ = username;
user_ = username;
}
class LoginResponse : public Deserializable
{
public:
void deserialize(const QJsonDocument &data) override;
void deserialize(const QJsonDocument &data) override;
inline QString getAccessToken();
inline QString getHomeServer();
inline QString getUserId();
inline QString getAccessToken();
inline QString getHomeServer();
inline QString getUserId();
private:
QString access_token_;
QString home_server_;
QString user_id_;
QString access_token_;
QString home_server_;
QString user_id_;
};
inline QString
LoginResponse::getAccessToken()
{
return access_token_;
return access_token_;
}
inline QString
LoginResponse::getHomeServer()
{
return home_server_;
return home_server_;
}
inline QString
LoginResponse::getUserId()
{
return user_id_;
return user_id_;
}

View file

@ -32,68 +32,68 @@
class LoginPage : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
~LoginPage();
LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
~LoginPage();
void reset();
void reset();
signals:
void backButtonClicked();
void backButtonClicked();
private slots:
// Callback for the back button.
void onBackButtonClicked();
// Callback for the back button.
void onBackButtonClicked();
// Callback for the login button.
void onLoginButtonClicked();
// Callback for the login button.
void onLoginButtonClicked();
// Callback for probing the server found in the mxid
void onMatrixIdEntered();
// Callback for probing the server found in the mxid
void onMatrixIdEntered();
// Callback for probing the manually entered server
void onServerAddressEntered();
// Callback for probing the manually entered server
void onServerAddressEntered();
// Displays errors produced during the login.
void loginError(QString error_message);
// Displays errors produced during the login.
void loginError(QString error_message);
// Callback for errors produced during server probing
void versionError(QString error_message);
// Callback for errors produced during server probing
void versionError(QString error_message);
// Callback for successful server probing
void versionSuccess();
// Callback for successful server probing
void versionSuccess();
private:
bool isMatrixIdValid();
bool isMatrixIdValid();
QVBoxLayout *top_layout_;
QVBoxLayout *top_layout_;
QHBoxLayout *top_bar_layout_;
QHBoxLayout *logo_layout_;
QHBoxLayout *button_layout_;
QHBoxLayout *top_bar_layout_;
QHBoxLayout *logo_layout_;
QHBoxLayout *button_layout_;
QLabel *logo_;
QLabel *error_label_;
QLabel *logo_;
QLabel *error_label_;
QHBoxLayout *serverLayout_;
QHBoxLayout *matrixidLayout_;
CircularProgress *spinner_;
QLabel *errorIcon_;
QString inferredServerAddress_;
QHBoxLayout *serverLayout_;
QHBoxLayout *matrixidLayout_;
CircularProgress *spinner_;
QLabel *errorIcon_;
QString inferredServerAddress_;
FlatButton *back_button_;
RaisedButton *login_button_;
FlatButton *back_button_;
RaisedButton *login_button_;
QWidget *form_widget_;
QHBoxLayout *form_wrapper_;
QVBoxLayout *form_layout_;
QWidget *form_widget_;
QHBoxLayout *form_wrapper_;
QVBoxLayout *form_layout_;
TextField *matrixid_input_;
TextField *password_input_;
TextField *serverInput_;
TextField *matrixid_input_;
TextField *password_input_;
TextField *serverInput_;
// Matrix client API provider.
QSharedPointer<MatrixClient> client_;
// Matrix client API provider.
QSharedPointer<MatrixClient> client_;
};

View file

@ -23,14 +23,14 @@
class LogoutDialog : public QFrame
{
Q_OBJECT
Q_OBJECT
public:
explicit LogoutDialog(QWidget *parent = nullptr);
explicit LogoutDialog(QWidget *parent = nullptr);
signals:
void closing(bool isLoggingOut);
void closing(bool isLoggingOut);
private:
FlatButton *confirmBtn_;
FlatButton *cancelBtn_;
FlatButton *confirmBtn_;
FlatButton *cancelBtn_;
};

View file

@ -32,64 +32,64 @@
class MainWindow : public QMainWindow
{
Q_OBJECT
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
static MainWindow *instance();
void saveCurrentWindowSize();
static MainWindow *instance();
void saveCurrentWindowSize();
protected:
void closeEvent(QCloseEvent *event);
void closeEvent(QCloseEvent *event);
private slots:
// Handle interaction with the tray icon.
void iconActivated(QSystemTrayIcon::ActivationReason reason);
// Handle interaction with the tray icon.
void iconActivated(QSystemTrayIcon::ActivationReason reason);
// Show the welcome page in the main window.
void showWelcomePage();
// Show the welcome page in the main window.
void showWelcomePage();
// Show the login page in the main window.
void showLoginPage();
// Show the login page in the main window.
void showLoginPage();
// Show the register page in the main window.
void showRegisterPage();
// Show the register page in the main window.
void showRegisterPage();
// Show the chat page and start communicating with the given access token.
void showChatPage(QString user_id, QString home_server, QString token);
// Show the chat page and start communicating with the given access token.
void showChatPage(QString user_id, QString home_server, QString token);
void removeOverlayProgressBar();
void removeOverlayProgressBar();
private:
bool hasActiveUser();
void restoreWindowSize();
bool hasActiveUser();
void restoreWindowSize();
static MainWindow *instance_;
static MainWindow *instance_;
// The initial welcome screen.
WelcomePage *welcome_page_;
// The initial welcome screen.
WelcomePage *welcome_page_;
// The login screen.
LoginPage *login_page_;
// The login screen.
LoginPage *login_page_;
// The register page.
RegisterPage *register_page_;
// The register page.
RegisterPage *register_page_;
// A stacked widget that handles the transitions between widgets.
SlidingStackWidget *sliding_stack_;
// A stacked widget that handles the transitions between widgets.
SlidingStackWidget *sliding_stack_;
// The main chat area.
ChatPage *chat_page_;
// The main chat area.
ChatPage *chat_page_;
// Used to hide undefined states between page transitions.
OverlayModal *progress_modal_;
CircularProgress *spinner_;
// Used to hide undefined states between page transitions.
OverlayModal *progress_modal_;
CircularProgress *spinner_;
// Matrix Client API provider.
QSharedPointer<MatrixClient> client_;
// Matrix Client API provider.
QSharedPointer<MatrixClient> client_;
// Tray icon that shows the unread message count.
TrayIcon *trayIcon_;
// Tray icon that shows the unread message count.
TrayIcon *trayIcon_;
};

View file

@ -25,24 +25,24 @@
class ProfileResponse : public Deserializable
{
public:
void deserialize(const QJsonDocument &data) override;
void deserialize(const QJsonDocument &data) override;
inline QUrl getAvatarUrl();
inline QString getDisplayName();
inline QUrl getAvatarUrl();
inline QString getDisplayName();
private:
QUrl avatar_url_;
QString display_name_;
QUrl avatar_url_;
QString display_name_;
};
inline QUrl
ProfileResponse::getAvatarUrl()
{
return avatar_url_;
return avatar_url_;
}
inline QString
ProfileResponse::getDisplayName()
{
return display_name_;
return display_name_;
}

View file

@ -26,44 +26,44 @@
class RoomSearchInput : public TextField
{
Q_OBJECT
Q_OBJECT
public:
explicit RoomSearchInput(QWidget *parent = nullptr);
explicit RoomSearchInput(QWidget *parent = nullptr);
signals:
void selectNextCompletion();
void selectPreviousCompletion();
void hiding();
void selectNextCompletion();
void selectPreviousCompletion();
void hiding();
protected:
void keyPressEvent(QKeyEvent *event) override;
void hideEvent(QHideEvent *event) override;
bool focusNextPrevChild(bool next) override;
void keyPressEvent(QKeyEvent *event) override;
void hideEvent(QHideEvent *event) override;
bool focusNextPrevChild(bool next) override;
};
class QuickSwitcher : public QFrame
{
Q_OBJECT
Q_OBJECT
public:
explicit QuickSwitcher(QWidget *parent = nullptr);
explicit QuickSwitcher(QWidget *parent = nullptr);
void setRoomList(const QMap<QString, QString> &rooms);
void setRoomList(const QMap<QString, QString> &rooms);
signals:
void closing();
void roomSelected(const QString &roomid);
void closing();
void roomSelected(const QString &roomid);
protected:
void keyPressEvent(QKeyEvent *event) override;
void showEvent(QShowEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void showEvent(QShowEvent *event) override;
private:
// Current highlighted selection from the completer.
int selection_ = -1;
// Current highlighted selection from the completer.
int selection_ = -1;
QVBoxLayout *topLayout_;
RoomSearchInput *roomSearch_;
QCompleter *completer_;
QVBoxLayout *topLayout_;
RoomSearchInput *roomSearch_;
QCompleter *completer_;
QMap<QString, QString> rooms_;
QMap<QString, QString> rooms_;
};

View file

@ -24,60 +24,60 @@
class RegisterRequest
{
public:
RegisterRequest();
RegisterRequest(const QString &username, const QString &password);
RegisterRequest();
RegisterRequest(const QString &username, const QString &password);
QByteArray serialize() noexcept;
QByteArray serialize() noexcept;
inline void setPassword(QString password);
inline void setUser(QString username);
inline void setPassword(QString password);
inline void setUser(QString username);
private:
QString user_;
QString password_;
QString user_;
QString password_;
};
inline void
RegisterRequest::setPassword(QString password)
{
password_ = password;
password_ = password;
}
inline void
RegisterRequest::setUser(QString username)
{
user_ = username;
user_ = username;
}
class RegisterResponse : public Deserializable
{
public:
void deserialize(const QJsonDocument &data) override;
void deserialize(const QJsonDocument &data) override;
inline QString getAccessToken();
inline QString getHomeServer();
inline QString getUserId();
inline QString getAccessToken();
inline QString getHomeServer();
inline QString getUserId();
private:
QString access_token_;
QString home_server_;
QString user_id_;
QString access_token_;
QString home_server_;
QString user_id_;
};
inline QString
RegisterResponse::getAccessToken()
{
return access_token_;
return access_token_;
}
inline QString
RegisterResponse::getHomeServer()
{
return home_server_;
return home_server_;
}
inline QString
RegisterResponse::getUserId()
{
return user_id_;
return user_id_;
}

View file

@ -31,44 +31,44 @@
class RegisterPage : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
~RegisterPage();
RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
~RegisterPage();
signals:
void backButtonClicked();
void backButtonClicked();
private slots:
void onBackButtonClicked();
void onRegisterButtonClicked();
void onBackButtonClicked();
void onRegisterButtonClicked();
// Display registration specific errors to the user.
void registerError(const QString &msg);
// Display registration specific errors to the user.
void registerError(const QString &msg);
private:
QVBoxLayout *top_layout_;
QVBoxLayout *top_layout_;
QHBoxLayout *back_layout_;
QHBoxLayout *logo_layout_;
QHBoxLayout *button_layout_;
QHBoxLayout *back_layout_;
QHBoxLayout *logo_layout_;
QHBoxLayout *button_layout_;
Avatar *logo_;
QLabel *error_label_;
Avatar *logo_;
QLabel *error_label_;
FlatButton *back_button_;
RaisedButton *register_button_;
FlatButton *back_button_;
RaisedButton *register_button_;
QWidget *form_widget_;
QHBoxLayout *form_wrapper_;
QVBoxLayout *form_layout_;
QWidget *form_widget_;
QHBoxLayout *form_wrapper_;
QVBoxLayout *form_layout_;
TextField *username_input_;
TextField *password_input_;
TextField *password_confirmation_;
TextField *server_input_;
TextField *username_input_;
TextField *password_input_;
TextField *password_confirmation_;
TextField *server_input_;
// Matrix client API provider.
QSharedPointer<MatrixClient> client_;
// Matrix client API provider.
QSharedPointer<MatrixClient> client_;
};

View file

@ -27,99 +27,102 @@
#include "RoomState.h"
struct DescInfo {
QString username;
QString userid;
QString body;
QString timestamp;
QString username;
QString userid;
QString body;
QString timestamp;
};
class RoomInfoListItem : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
RoomInfoListItem(QSharedPointer<RoomSettings> settings, 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 clearUnreadMessageCount();
void setState(const RoomState &state);
void updateUnreadMessageCount(int count);
void clearUnreadMessageCount();
void setState(const RoomState &state);
inline bool isPressed() const;
inline RoomState state() const;
inline void setAvatar(const QImage &avatar_image);
inline int unreadMessageCount() const;
inline void setDescriptionMessage(const DescInfo &info);
inline bool isPressed() const;
inline RoomState state() const;
inline void setAvatar(const QImage &avatar_image);
inline int unreadMessageCount() const;
inline void setDescriptionMessage(const DescInfo &info);
signals:
void clicked(const QString &room_id);
void clicked(const QString &room_id);
public slots:
void setPressedState(bool state);
void setPressedState(bool state);
protected:
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
private:
QString notificationText();
QString notificationText();
const int Padding = 7;
const int IconSize = 48;
const int Padding = 7;
const int IconSize = 48;
RippleOverlay *ripple_overlay_;
RippleOverlay *ripple_overlay_;
RoomState state_;
RoomState state_;
QString roomId_;
QString roomName_;
QString roomId_;
QString roomName_;
DescInfo lastMsgInfo_;
DescInfo lastMsgInfo_;
QPixmap roomAvatar_;
QPixmap roomAvatar_;
Menu *menu_;
QAction *toggleNotifications_;
Menu *menu_;
QAction *toggleNotifications_;
QSharedPointer<RoomSettings> roomSettings_;
QSharedPointer<RoomSettings> roomSettings_;
bool isPressed_ = false;
bool isPressed_ = false;
int maxHeight_;
int unreadMsgCount_ = 0;
int maxHeight_;
int unreadMsgCount_ = 0;
};
inline int
RoomInfoListItem::unreadMessageCount() const
{
return unreadMsgCount_;
return unreadMsgCount_;
}
inline bool
RoomInfoListItem::isPressed() const
{
return isPressed_;
return isPressed_;
}
inline RoomState
RoomInfoListItem::state() const
{
return state_;
return state_;
}
inline void
RoomInfoListItem::setAvatar(const QImage &img)
{
roomAvatar_ =
QPixmap::fromImage(img.scaled(IconSize, IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
update();
roomAvatar_ = QPixmap::fromImage(
img.scaled(IconSize, IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
update();
}
inline void
RoomInfoListItem::setDescriptionMessage(const DescInfo &info)
{
lastMsgInfo_ = info;
lastMsgInfo_ = info;
}

View file

@ -29,37 +29,37 @@
class RoomList : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
~RoomList();
RoomList(QSharedPointer<MatrixClient> client, QWidget *parent = 0);
~RoomList();
void setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
const QMap<QString, RoomState> &states);
void sync(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 clear();
void clear();
signals:
void roomChanged(const QString &room_id);
void totalUnreadMessageCountUpdated(int count);
void roomChanged(const QString &room_id);
void totalUnreadMessageCountUpdated(int count);
public slots:
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
void highlightSelectedRoom(const QString &room_id);
void updateUnreadMessageCount(const QString &roomid, int count);
void updateRoomDescription(const QString &roomid, const DescInfo &info);
void updateRoomAvatar(const QString &roomid, const QPixmap &img);
void highlightSelectedRoom(const QString &room_id);
void updateUnreadMessageCount(const QString &roomid, int count);
void updateRoomDescription(const QString &roomid, const DescInfo &info);
private:
void calculateUnreadMessageCount();
void calculateUnreadMessageCount();
QVBoxLayout *topLayout_;
QVBoxLayout *contentsLayout_;
QScrollArea *scrollArea_;
QWidget *scrollAreaContents_;
QVBoxLayout *topLayout_;
QVBoxLayout *contentsLayout_;
QScrollArea *scrollArea_;
QWidget *scrollAreaContents_;
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
QSharedPointer<MatrixClient> client_;
QSharedPointer<MatrixClient> client_;
};

View file

@ -25,32 +25,32 @@
class RoomMessages : public Deserializable
{
public:
void deserialize(const QJsonDocument &data) override;
void deserialize(const QJsonDocument &data) override;
inline QString start() const;
inline QString end() const;
inline QJsonArray chunk() const;
inline QString start() const;
inline QString end() const;
inline QJsonArray chunk() const;
private:
QString start_;
QString end_;
QJsonArray chunk_;
QString start_;
QString end_;
QJsonArray chunk_;
};
inline QString
RoomMessages::start() const
{
return start_;
return start_;
}
inline QString
RoomMessages::end() const
{
return end_;
return end_;
}
inline QJsonArray
RoomMessages::chunk() const
{
return chunk_;
return chunk_;
}

View file

@ -22,34 +22,34 @@
class RoomSettings
{
public:
RoomSettings(QString room_id)
{
path_ = QString("notifications/%1").arg(room_id);
isNotificationsEnabled_ = true;
RoomSettings(QString room_id)
{
path_ = QString("notifications/%1").arg(room_id);
isNotificationsEnabled_ = true;
QSettings settings;
QSettings settings;
if (settings.contains(path_))
isNotificationsEnabled_ = settings.value(path_).toBool();
else
settings.setValue(path_, isNotificationsEnabled_);
};
if (settings.contains(path_))
isNotificationsEnabled_ = settings.value(path_).toBool();
else
settings.setValue(path_, isNotificationsEnabled_);
};
bool isNotificationsEnabled()
{
return isNotificationsEnabled_;
};
bool isNotificationsEnabled()
{
return isNotificationsEnabled_;
};
void toggleNotifications()
{
isNotificationsEnabled_ = !isNotificationsEnabled_;
void toggleNotifications()
{
isNotificationsEnabled_ = !isNotificationsEnabled_;
QSettings settings;
settings.setValue(path_, isNotificationsEnabled_);
}
QSettings settings;
settings.setValue(path_, isNotificationsEnabled_);
}
private:
QString path_;
QString path_;
bool isNotificationsEnabled_;
bool isNotificationsEnabled_;
};

View file

@ -32,56 +32,57 @@
class SlidingStackWidget : public QStackedWidget
{
Q_OBJECT
Q_OBJECT
public:
// Defines the animation direction.
enum class AnimationDirection { LEFT_TO_RIGHT, RIGHT_TO_LEFT, AUTOMATIC };
// Defines the animation direction.
enum class AnimationDirection { LEFT_TO_RIGHT, RIGHT_TO_LEFT, AUTOMATIC };
SlidingStackWidget(QWidget *parent);
~SlidingStackWidget();
SlidingStackWidget(QWidget *parent);
~SlidingStackWidget();
public slots:
// Move to the next widget.
void slideInNext();
// Move to the next widget.
void slideInNext();
// Move to the previous widget.
void slideInPrevious();
// Move to the previous widget.
void slideInPrevious();
// Move to a widget by index.
void slideInIndex(int index, AnimationDirection direction = AnimationDirection::AUTOMATIC);
// Move to a widget by index.
void slideInIndex(int index, AnimationDirection direction = AnimationDirection::AUTOMATIC);
int getWidgetIndex(QWidget *widget);
int getWidgetIndex(QWidget *widget);
signals:
// Internal signal to alert the engine for the animation's end.
void animationFinished();
// Internal signal to alert the engine for the animation's end.
void animationFinished();
protected slots:
// Internal slot to handle the end of the animation.
void onAnimationFinished();
// Internal slot to handle the end of the animation.
void onAnimationFinished();
protected:
// The method that does the main work for the widget transition.
void slideInWidget(QWidget *widget, AnimationDirection direction = AnimationDirection::AUTOMATIC);
// The method that does the main work for the widget transition.
void slideInWidget(QWidget *widget,
AnimationDirection direction = AnimationDirection::AUTOMATIC);
// Indicates whether or not the animation is active.
bool active_;
// Indicates whether or not the animation is active.
bool active_;
// The widget currently displayed.
QWidget *window_;
// The widget currently displayed.
QWidget *window_;
// The speed of the animation in milliseconds.
int speed_;
// The speed of the animation in milliseconds.
int speed_;
// The animation type.
QEasingCurve::Type animation_type_;
// The animation type.
QEasingCurve::Type animation_type_;
// Current widget's index.
int now_;
// Current widget's index.
int now_;
// Reference point.
QPoint current_position_;
// Reference point.
QPoint current_position_;
// Next widget's to show index.
int next_;
// Next widget's to show index.
int next_;
};

View file

@ -21,15 +21,15 @@
class Splitter : public QSplitter
{
Q_OBJECT
Q_OBJECT
public:
explicit Splitter(QWidget *parent = nullptr);
explicit Splitter(QWidget *parent = nullptr);
private:
void onSplitterMoved(int pos, int index);
void onSplitterMoved(int pos, int index);
int moveEventLimit_ = 50;
int moveEventLimit_ = 50;
int leftMoveCount_ = 0;
int rightMoveCount_ = 0;
int leftMoveCount_ = 0;
int rightMoveCount_ = 0;
};

View file

@ -27,187 +27,187 @@
class Event : public Deserializable
{
public:
inline QJsonObject content() const;
inline QJsonObject unsigned_content() const;
inline QJsonObject content() const;
inline QJsonObject unsigned_content() const;
inline QString sender() const;
inline QString state_key() const;
inline QString type() const;
inline QString eventId() const;
inline QString sender() const;
inline QString state_key() const;
inline QString type() const;
inline QString eventId() const;
inline uint64_t timestamp() const;
inline uint64_t timestamp() const;
void deserialize(const QJsonValue &data) override;
void deserialize(const QJsonValue &data) override;
private:
QJsonObject content_;
QJsonObject unsigned_;
QJsonObject content_;
QJsonObject unsigned_;
QString sender_;
QString state_key_;
QString type_;
QString event_id_;
QString sender_;
QString state_key_;
QString type_;
QString event_id_;
uint64_t origin_server_ts_;
uint64_t origin_server_ts_;
};
inline QJsonObject
Event::content() const
{
return content_;
return content_;
}
inline QJsonObject
Event::unsigned_content() const
{
return unsigned_;
return unsigned_;
}
inline QString
Event::sender() const
{
return sender_;
return sender_;
}
inline QString
Event::state_key() const
{
return state_key_;
return state_key_;
}
inline QString
Event::type() const
{
return type_;
return type_;
}
inline QString
Event::eventId() const
{
return event_id_;
return event_id_;
}
inline uint64_t
Event::timestamp() const
{
return origin_server_ts_;
return origin_server_ts_;
}
class State : public Deserializable
{
public:
void deserialize(const QJsonValue &data) override;
inline QJsonArray events() const;
void deserialize(const QJsonValue &data) override;
inline QJsonArray events() const;
private:
QJsonArray events_;
QJsonArray events_;
};
inline QJsonArray
State::events() const
{
return events_;
return events_;
}
class Timeline : public Deserializable
{
public:
inline QJsonArray events() const;
inline QString previousBatch() const;
inline bool limited() const;
inline QJsonArray events() const;
inline QString previousBatch() const;
inline bool limited() const;
void deserialize(const QJsonValue &data) override;
void deserialize(const QJsonValue &data) override;
private:
QJsonArray events_;
QString prev_batch_;
bool limited_;
QJsonArray events_;
QString prev_batch_;
bool limited_;
};
inline QJsonArray
Timeline::events() const
{
return events_;
return events_;
}
inline QString
Timeline::previousBatch() const
{
return prev_batch_;
return prev_batch_;
}
inline bool
Timeline::limited() const
{
return limited_;
return limited_;
}
// TODO: Add support for ehpmeral, account_data, undread_notifications
class JoinedRoom : public Deserializable
{
public:
inline State state() const;
inline Timeline timeline() const;
inline State state() const;
inline Timeline timeline() const;
void deserialize(const QJsonValue &data) override;
void deserialize(const QJsonValue &data) override;
private:
State state_;
Timeline timeline_;
/* Ephemeral ephemeral_; */
/* AccountData account_data_; */
/* UnreadNotifications unread_notifications_; */
State state_;
Timeline timeline_;
/* Ephemeral ephemeral_; */
/* AccountData account_data_; */
/* UnreadNotifications unread_notifications_; */
};
inline State
JoinedRoom::state() const
{
return state_;
return state_;
}
inline Timeline
JoinedRoom::timeline() const
{
return timeline_;
return timeline_;
}
// TODO: Add support for invited and left rooms.
class Rooms : public Deserializable
{
public:
inline QMap<QString, JoinedRoom> join() const;
void deserialize(const QJsonValue &data) override;
inline QMap<QString, JoinedRoom> join() const;
void deserialize(const QJsonValue &data) override;
private:
QMap<QString, JoinedRoom> join_;
QMap<QString, JoinedRoom> join_;
};
inline QMap<QString, JoinedRoom>
Rooms::join() const
{
return join_;
return join_;
}
class SyncResponse : public Deserializable
{
public:
void deserialize(const QJsonDocument &data) override;
inline QString nextBatch() const;
inline Rooms rooms() const;
void deserialize(const QJsonDocument &data) override;
inline QString nextBatch() const;
inline Rooms rooms() const;
private:
QString next_batch_;
Rooms rooms_;
QString next_batch_;
Rooms rooms_;
};
inline Rooms
SyncResponse::rooms() const
{
return rooms_;
return rooms_;
}
inline QString
SyncResponse::nextBatch() const
{
return next_batch_;
return next_batch_;
}

View file

@ -28,31 +28,31 @@
class MsgCountComposedIcon : public QIconEngine
{
public:
MsgCountComposedIcon(const QString &filename);
MsgCountComposedIcon(const QString &filename);
virtual void paint(QPainter *p, const QRect &rect, QIcon::Mode mode, QIcon::State state);
virtual QIconEngine *clone() const;
virtual void paint(QPainter *p, const QRect &rect, QIcon::Mode mode, QIcon::State state);
virtual QIconEngine *clone() const;
int msgCount = 0;
int msgCount = 0;
private:
const int BubbleDiameter = 17;
const int BubbleDiameter = 17;
QIcon icon_;
QIcon icon_;
};
class TrayIcon : public QSystemTrayIcon
{
Q_OBJECT
Q_OBJECT
public:
TrayIcon(const QString &filename, QWidget *parent);
TrayIcon(const QString &filename, QWidget *parent);
public slots:
void setUnreadCount(int count);
void setUnreadCount(int count);
private:
QAction *viewAction_;
QAction *quitAction_;
QAction *viewAction_;
QAction *quitAction_;
MsgCountComposedIcon *icon_;
MsgCountComposedIcon *icon_;
};

View file

@ -29,47 +29,47 @@
class UserInfoWidget : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
UserInfoWidget(QWidget *parent = 0);
~UserInfoWidget();
UserInfoWidget(QWidget *parent = 0);
~UserInfoWidget();
void setAvatar(const QImage &img);
void setDisplayName(const QString &name);
void setUserId(const QString &userid);
void setAvatar(const QImage &img);
void setDisplayName(const QString &name);
void setUserId(const QString &userid);
void reset();
void reset();
signals:
void logout();
void logout();
protected:
void resizeEvent(QResizeEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private slots:
void closeLogoutDialog(bool isLoggingOut);
void closeLogoutDialog(bool isLoggingOut);
private:
Avatar *userAvatar_;
Avatar *userAvatar_;
QHBoxLayout *topLayout_;
QHBoxLayout *avatarLayout_;
QVBoxLayout *textLayout_;
QHBoxLayout *buttonLayout_;
QHBoxLayout *topLayout_;
QHBoxLayout *avatarLayout_;
QVBoxLayout *textLayout_;
QHBoxLayout *buttonLayout_;
FlatButton *logoutButton_;
FlatButton *logoutButton_;
QLabel *displayNameLabel_;
QLabel *userIdLabel_;
QLabel *displayNameLabel_;
QLabel *userIdLabel_;
QString display_name_;
QString user_id_;
QString display_name_;
QString user_id_;
QImage avatar_image_;
QImage avatar_image_;
OverlayModal *logoutModal_;
LogoutDialog *logoutDialog_;
OverlayModal *logoutModal_;
LogoutDialog *logoutDialog_;
int logoutButtonSize_;
int logoutButtonSize_;
};

View file

@ -25,16 +25,16 @@
class VersionsResponse : public Deserializable
{
public:
void deserialize(const QJsonDocument &data) override;
void deserialize(const QJsonDocument &data) override;
bool isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch);
bool isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch);
private:
struct Version_ {
unsigned int major_;
unsigned int minor_;
unsigned int patch_;
};
struct Version_ {
unsigned int major_;
unsigned int minor_;
unsigned int patch_;
};
QVector<Version_> supported_versions_;
QVector<Version_> supported_versions_;
};

View file

@ -27,32 +27,32 @@
class WelcomePage : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
explicit WelcomePage(QWidget *parent = 0);
~WelcomePage();
explicit WelcomePage(QWidget *parent = 0);
~WelcomePage();
signals:
// Notify that the user wants to login in.
void userLogin();
// Notify that the user wants to login in.
void userLogin();
// Notify that the user wants to register.
void userRegister();
// Notify that the user wants to register.
void userRegister();
private slots:
void onLoginButtonClicked();
void onRegisterButtonClicked();
void onLoginButtonClicked();
void onRegisterButtonClicked();
private:
QVBoxLayout *top_layout_;
QHBoxLayout *button_layout_;
QVBoxLayout *top_layout_;
QHBoxLayout *button_layout_;
QLabel *intro_banner_;
QLabel *intro_text_;
QLabel *intro_banner_;
QLabel *intro_text_;
QSpacerItem *button_spacer_;
QSpacerItem *button_spacer_;
RaisedButton *register_button_;
RaisedButton *login_button_;
RaisedButton *register_button_;
RaisedButton *login_button_;
};

View file

@ -31,19 +31,19 @@ class AliasesEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QList<QString> aliases() const;
inline QList<QString> aliases() const;
private:
QList<QString> aliases_;
QList<QString> aliases_;
};
inline QList<QString>
AliasesEventContent::aliases() const
{
return aliases_;
return aliases_;
}
} // namespace events
} // namespace matrix

View file

@ -35,19 +35,19 @@ class AvatarEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QUrl url() const;
inline QUrl url() const;
private:
QUrl url_;
QUrl url_;
};
inline QUrl
AvatarEventContent::url() const
{
return url_;
return url_;
}
} // namespace events
} // namespace matrix

View file

@ -37,19 +37,19 @@ class CanonicalAliasEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QString alias() const;
inline QString alias() const;
private:
QString alias_;
QString alias_;
};
inline QString
CanonicalAliasEventContent::alias() const
{
return alias_;
return alias_;
}
} // namespace events
} // namespace matrix

View file

@ -34,20 +34,20 @@ class CreateEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QString creator() const;
inline QString creator() const;
private:
// The user_id of the room creator. This is set by the homeserver.
QString creator_;
// The user_id of the room creator. This is set by the homeserver.
QString creator_;
};
inline QString
CreateEventContent::creator() const
{
return creator_;
return creator_;
}
} // namespace events
} // namespace matrix

View file

@ -27,30 +27,30 @@ namespace matrix
namespace events
{
enum class EventType {
/// m.room.aliases
RoomAliases,
/// m.room.avatar
RoomAvatar,
/// m.room.canonical_alias
RoomCanonicalAlias,
/// m.room.create
RoomCreate,
/// m.room.history_visibility
RoomHistoryVisibility,
/// m.room.join_rules
RoomJoinRules,
/// m.room.member
RoomMember,
/// m.room.message
RoomMessage,
/// m.room.name
RoomName,
/// m.room.power_levels
RoomPowerLevels,
/// m.room.topic
RoomTopic,
// Unsupported event
Unsupported,
/// m.room.aliases
RoomAliases,
/// m.room.avatar
RoomAvatar,
/// m.room.canonical_alias
RoomCanonicalAlias,
/// m.room.create
RoomCreate,
/// m.room.history_visibility
RoomHistoryVisibility,
/// m.room.join_rules
RoomJoinRules,
/// m.room.member
RoomMember,
/// m.room.message
RoomMessage,
/// m.room.name
RoomName,
/// m.room.power_levels
RoomPowerLevels,
/// m.room.topic
RoomTopic,
// Unsupported event
Unsupported,
};
EventType
@ -67,92 +67,92 @@ class Event
, public Serializable
{
public:
inline Content content() const;
inline EventType eventType() const;
inline Content content() const;
inline EventType eventType() const;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
private:
Content content_;
EventType type_;
Content content_;
EventType type_;
};
template<class Content>
inline Content
Event<Content>::content() const
{
return content_;
return content_;
}
template<class Content>
inline EventType
Event<Content>::eventType() const
{
return type_;
return type_;
}
template<class Content>
void
Event<Content>::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("Event is not a JSON object");
if (!data.isObject())
throw DeserializationException("Event is not a JSON object");
auto object = data.toObject();
auto object = data.toObject();
content_.deserialize(object.value("content"));
type_ = extractEventType(object);
content_.deserialize(object.value("content"));
type_ = extractEventType(object);
}
template<class Content>
QJsonObject
Event<Content>::serialize() const
{
QJsonObject object;
QJsonObject object;
switch (type_) {
case EventType::RoomAliases:
object["type"] = "m.room.aliases";
break;
case EventType::RoomAvatar:
object["type"] = "m.room.avatar";
break;
case EventType::RoomCanonicalAlias:
object["type"] = "m.room.canonical_alias";
break;
case EventType::RoomCreate:
object["type"] = "m.room.create";
break;
case EventType::RoomHistoryVisibility:
object["type"] = "m.room.history_visibility";
break;
case EventType::RoomJoinRules:
object["type"] = "m.room.join_rules";
break;
case EventType::RoomMember:
object["type"] = "m.room.member";
break;
case EventType::RoomMessage:
object["type"] = "m.room.message";
break;
case EventType::RoomName:
object["type"] = "m.room.name";
break;
case EventType::RoomPowerLevels:
object["type"] = "m.room.power_levels";
break;
case EventType::RoomTopic:
object["type"] = "m.room.topic";
break;
case EventType::Unsupported:
qWarning() << "Unsupported type to serialize";
break;
}
switch (type_) {
case EventType::RoomAliases:
object["type"] = "m.room.aliases";
break;
case EventType::RoomAvatar:
object["type"] = "m.room.avatar";
break;
case EventType::RoomCanonicalAlias:
object["type"] = "m.room.canonical_alias";
break;
case EventType::RoomCreate:
object["type"] = "m.room.create";
break;
case EventType::RoomHistoryVisibility:
object["type"] = "m.room.history_visibility";
break;
case EventType::RoomJoinRules:
object["type"] = "m.room.join_rules";
break;
case EventType::RoomMember:
object["type"] = "m.room.member";
break;
case EventType::RoomMessage:
object["type"] = "m.room.message";
break;
case EventType::RoomName:
object["type"] = "m.room.name";
break;
case EventType::RoomPowerLevels:
object["type"] = "m.room.power_levels";
break;
case EventType::RoomTopic:
object["type"] = "m.room.topic";
break;
case EventType::Unsupported:
qWarning() << "Unsupported type to serialize";
break;
}
object["content"] = content_.serialize();
object["content"] = content_.serialize();
return object;
return object;
}
} // namespace events
} // namespace matrix

View file

@ -26,10 +26,10 @@ namespace matrix
namespace events
{
enum class HistoryVisibility {
Invited,
Joined,
Shared,
WorldReadable,
Invited,
Joined,
Shared,
WorldReadable,
};
class HistoryVisibilityEventContent
@ -37,19 +37,19 @@ class HistoryVisibilityEventContent
, public Serializable
{
public:
inline HistoryVisibility historyVisibility() const;
inline HistoryVisibility historyVisibility() const;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
private:
HistoryVisibility history_visibility_;
HistoryVisibility history_visibility_;
};
inline HistoryVisibility
HistoryVisibilityEventContent::historyVisibility() const
{
return history_visibility_;
return history_visibility_;
}
} // namespace events
} // namespace matrix

View file

@ -26,18 +26,18 @@ namespace matrix
namespace events
{
enum class JoinRule {
// A user who wishes to join the room must first receive
// an invite to the room from someone already inside of the room.
Invite,
// A user who wishes to join the room must first receive
// an invite to the room from someone already inside of the room.
Invite,
// Reserved but not yet implemented by the Matrix specification.
Knock,
// Reserved but not yet implemented by the Matrix specification.
Knock,
// Reserved but not yet implemented by the Matrix specification.
Private,
// Reserved but not yet implemented by the Matrix specification.
Private,
/// Anyone can join the room without any prior action.
Public,
/// Anyone can join the room without any prior action.
Public,
};
/*
@ -49,19 +49,19 @@ class JoinRulesEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline JoinRule joinRule() const;
inline JoinRule joinRule() const;
private:
JoinRule join_rule_;
JoinRule join_rule_;
};
inline JoinRule
JoinRulesEventContent::joinRule() const
{
return join_rule_;
return join_rule_;
}
} // namespace events
} // namespace matrix

View file

@ -27,20 +27,20 @@ namespace matrix
namespace events
{
enum class Membership {
// The user is banned.
Ban,
// The user is banned.
Ban,
// The user has been invited.
Invite,
// The user has been invited.
Invite,
// The user has joined.
Join,
// The user has joined.
Join,
// The user has requested to join.
Knock,
// The user has requested to join.
Knock,
// The user has left.
Leave,
// The user has left.
Leave,
};
/*
@ -52,35 +52,35 @@ class MemberEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QUrl avatarUrl() const;
inline QString displayName() const;
inline Membership membershipState() const;
inline QUrl avatarUrl() const;
inline QString displayName() const;
inline Membership membershipState() const;
private:
QUrl avatar_url_;
QString display_name_;
Membership membership_state_;
QUrl avatar_url_;
QString display_name_;
Membership membership_state_;
};
inline QUrl
MemberEventContent::avatarUrl() const
{
return avatar_url_;
return avatar_url_;
}
inline QString
MemberEventContent::displayName() const
{
return display_name_;
return display_name_;
}
inline Membership
MemberEventContent::membershipState() const
{
return membership_state_;
return membership_state_;
}
} // namespace events
} // namespace matrix

View file

@ -28,38 +28,38 @@ template<class MsgContent>
class MessageEvent : public RoomEvent<MessageEventContent>
{
public:
inline MsgContent msgContent() const;
inline MsgContent msgContent() const;
void deserialize(const QJsonValue &data) override;
void deserialize(const QJsonValue &data) override;
private:
MsgContent msg_content_;
MsgContent msg_content_;
};
template<class MsgContent>
inline MsgContent
MessageEvent<MsgContent>::msgContent() const
{
return msg_content_;
return msg_content_;
}
template<class MsgContent>
void
MessageEvent<MsgContent>::deserialize(const QJsonValue &data)
{
RoomEvent<MessageEventContent>::deserialize(data);
RoomEvent<MessageEventContent>::deserialize(data);
msg_content_.deserialize(data.toObject().value("content").toObject());
msg_content_.deserialize(data.toObject().value("content").toObject());
}
namespace messages
{
struct ThumbnailInfo {
int h;
int w;
int size;
int h;
int w;
int size;
QString mimetype;
QString mimetype;
};
} // namespace messages
} // namespace events

View file

@ -26,32 +26,32 @@ namespace matrix
namespace events
{
enum class MessageEventType {
// m.audio
Audio,
// m.audio
Audio,
// m.emote
Emote,
// m.emote
Emote,
// m.file
File,
// m.file
File,
// m.image
Image,
// m.image
Image,
// m.location
Location,
// m.location
Location,
// m.notice
Notice,
// m.notice
Notice,
// m.text
Text,
// m.text
Text,
// m.video
Video,
// m.video
Video,
// Unrecognized message type
Unknown,
// Unrecognized message type
Unknown,
};
MessageEventType
@ -62,19 +62,19 @@ class MessageEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QString body() const;
inline QString body() const;
private:
QString body_;
QString body_;
};
inline QString
MessageEventContent::body() const
{
return body_;
return body_;
}
} // namespace events
} // namespace matrix

View file

@ -34,19 +34,19 @@ class NameEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QString name() const;
inline QString name() const;
private:
QString name_;
QString name_;
};
inline QString
NameEventContent::name() const
{
return name_;
return name_;
}
} // namespace events
} // namespace matrix

View file

@ -27,9 +27,9 @@ namespace matrix
namespace events
{
enum class PowerLevels {
User = 0,
Moderator = 50,
Admin = 100,
User = 0,
Moderator = 50,
Admin = 100,
};
/*
@ -41,75 +41,75 @@ class PowerLevelsEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline int banLevel() const;
inline int inviteLevel() const;
inline int kickLevel() const;
inline int redactLevel() const;
inline int banLevel() const;
inline int inviteLevel() const;
inline int kickLevel() const;
inline int redactLevel() const;
inline int eventsDefaultLevel() const;
inline int stateDefaultLevel() const;
inline int usersDefaultLevel() const;
inline int eventsDefaultLevel() const;
inline int stateDefaultLevel() const;
inline int usersDefaultLevel() const;
int eventLevel(QString event_type) const;
int userLevel(QString user_id) const;
int eventLevel(QString event_type) const;
int userLevel(QString user_id) const;
private:
int ban_ = static_cast<int>(PowerLevels::Moderator);
int invite_ = static_cast<int>(PowerLevels::Moderator);
int kick_ = static_cast<int>(PowerLevels::Moderator);
int redact_ = static_cast<int>(PowerLevels::Moderator);
int ban_ = static_cast<int>(PowerLevels::Moderator);
int invite_ = static_cast<int>(PowerLevels::Moderator);
int kick_ = static_cast<int>(PowerLevels::Moderator);
int redact_ = static_cast<int>(PowerLevels::Moderator);
int events_default_ = static_cast<int>(PowerLevels::User);
int state_default_ = static_cast<int>(PowerLevels::Moderator);
int users_default_ = static_cast<int>(PowerLevels::User);
int events_default_ = static_cast<int>(PowerLevels::User);
int state_default_ = static_cast<int>(PowerLevels::Moderator);
int users_default_ = static_cast<int>(PowerLevels::User);
QMap<QString, int> events_;
QMap<QString, int> users_;
QMap<QString, int> events_;
QMap<QString, int> users_;
};
inline int
PowerLevelsEventContent::banLevel() const
{
return ban_;
return ban_;
}
inline int
PowerLevelsEventContent::inviteLevel() const
{
return invite_;
return invite_;
}
inline int
PowerLevelsEventContent::kickLevel() const
{
return kick_;
return kick_;
}
inline int
PowerLevelsEventContent::redactLevel() const
{
return redact_;
return redact_;
}
inline int
PowerLevelsEventContent::eventsDefaultLevel() const
{
return events_default_;
return events_default_;
}
inline int
PowerLevelsEventContent::stateDefaultLevel() const
{
return state_default_;
return state_default_;
}
inline int
PowerLevelsEventContent::usersDefaultLevel() const
{
return users_default_;
return users_default_;
}
} // namespace events
} // namespace matrix

View file

@ -30,89 +30,89 @@ template<class Content>
class RoomEvent : public Event<Content>
{
public:
inline QString eventId() const;
inline QString roomId() const;
inline QString sender() const;
inline uint64_t timestamp() const;
inline QString eventId() const;
inline QString roomId() const;
inline QString sender() const;
inline uint64_t timestamp() const;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
private:
QString event_id_;
QString room_id_;
QString sender_;
QString event_id_;
QString room_id_;
QString sender_;
uint64_t origin_server_ts_;
uint64_t origin_server_ts_;
};
template<class Content>
inline QString
RoomEvent<Content>::eventId() const
{
return event_id_;
return event_id_;
}
template<class Content>
inline QString
RoomEvent<Content>::roomId() const
{
return room_id_;
return room_id_;
}
template<class Content>
inline QString
RoomEvent<Content>::sender() const
{
return sender_;
return sender_;
}
template<class Content>
inline uint64_t
RoomEvent<Content>::timestamp() const
{
return origin_server_ts_;
return origin_server_ts_;
}
template<class Content>
void
RoomEvent<Content>::deserialize(const QJsonValue &data)
{
Event<Content>::deserialize(data);
Event<Content>::deserialize(data);
auto object = data.toObject();
auto object = data.toObject();
if (!object.contains("event_id"))
throw DeserializationException("event_id key is missing");
if (!object.contains("event_id"))
throw DeserializationException("event_id key is missing");
if (!object.contains("origin_server_ts"))
throw DeserializationException("origin_server_ts key is missing");
if (!object.contains("origin_server_ts"))
throw DeserializationException("origin_server_ts key is missing");
// FIXME: Synapse doesn't include room id?!
/* if (!object.contains("room_id")) */
/* throw DeserializationException("room_id key is missing"); */
// FIXME: Synapse doesn't include room id?!
/* if (!object.contains("room_id")) */
/* throw DeserializationException("room_id key is missing"); */
if (!object.contains("sender"))
throw DeserializationException("sender key is missing");
if (!object.contains("sender"))
throw DeserializationException("sender key is missing");
event_id_ = object.value("event_id").toString();
room_id_ = object.value("room_id").toString();
sender_ = object.value("sender").toString();
origin_server_ts_ = object.value("origin_server_ts").toDouble();
event_id_ = object.value("event_id").toString();
room_id_ = object.value("room_id").toString();
sender_ = object.value("sender").toString();
origin_server_ts_ = object.value("origin_server_ts").toDouble();
}
template<class Content>
QJsonObject
RoomEvent<Content>::serialize() const
{
QJsonObject object = Event<Content>::serialize();
QJsonObject object = Event<Content>::serialize();
object["event_id"] = event_id_;
object["room_id"] = room_id_;
object["sender"] = sender_;
object["origin_server_ts"] = QJsonValue(static_cast<qint64>(origin_server_ts_));
object["event_id"] = event_id_;
object["room_id"] = room_id_;
object["sender"] = sender_;
object["origin_server_ts"] = QJsonValue(static_cast<qint64>(origin_server_ts_));
return object;
return object;
}
} // namespace events
} // namespace matrix

View file

@ -29,62 +29,62 @@ template<class Content>
class StateEvent : public RoomEvent<Content>
{
public:
inline QString stateKey() const;
inline Content previousContent() const;
inline QString stateKey() const;
inline Content previousContent() const;
void deserialize(const QJsonValue &data);
QJsonObject serialize() const;
void deserialize(const QJsonValue &data);
QJsonObject serialize() const;
private:
QString state_key_;
Content prev_content_;
QString state_key_;
Content prev_content_;
};
template<class Content>
inline QString
StateEvent<Content>::stateKey() const
{
return state_key_;
return state_key_;
}
template<class Content>
inline Content
StateEvent<Content>::previousContent() const
{
return prev_content_;
return prev_content_;
}
template<class Content>
void
StateEvent<Content>::deserialize(const QJsonValue &data)
{
RoomEvent<Content>::deserialize(data);
RoomEvent<Content>::deserialize(data);
auto object = data.toObject();
auto object = data.toObject();
if (!object.contains("state_key"))
throw DeserializationException("state_key key is missing");
if (!object.contains("state_key"))
throw DeserializationException("state_key key is missing");
state_key_ = object.value("state_key").toString();
state_key_ = object.value("state_key").toString();
if (object.contains("prev_content"))
prev_content_.deserialize(object.value("prev_content"));
if (object.contains("prev_content"))
prev_content_.deserialize(object.value("prev_content"));
}
template<class Content>
QJsonObject
StateEvent<Content>::serialize() const
{
QJsonObject object = RoomEvent<Content>::serialize();
QJsonObject object = RoomEvent<Content>::serialize();
object["state_key"] = state_key_;
object["state_key"] = state_key_;
auto prev = prev_content_.serialize();
auto prev = prev_content_.serialize();
if (!prev.isEmpty())
object["prev_content"] = prev;
if (!prev.isEmpty())
object["prev_content"] = prev;
return object;
return object;
}
} // namespace events
} // namespace matrix

View file

@ -34,19 +34,19 @@ class TopicEventContent
, public Serializable
{
public:
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
void deserialize(const QJsonValue &data) override;
QJsonObject serialize() const override;
inline QString topic() const;
inline QString topic() const;
private:
QString topic_;
QString topic_;
};
inline QString
TopicEventContent::topic() const
{
return topic_;
return topic_;
}
} // namespace events
} // namespace matrix

View file

@ -28,35 +28,35 @@ namespace events
namespace messages
{
struct AudioInfo {
uint64_t duration;
int size;
uint64_t duration;
int size;
QString mimetype;
QString mimetype;
};
class Audio : public Deserializable
{
public:
inline QString url() const;
inline AudioInfo info() const;
inline QString url() const;
inline AudioInfo info() const;
void deserialize(const QJsonObject &object) override;
void deserialize(const QJsonObject &object) override;
private:
QString url_;
AudioInfo info_;
QString url_;
AudioInfo info_;
};
inline QString
Audio::url() const
{
return url_;
return url_;
}
inline AudioInfo
Audio::info() const
{
return info_;
return info_;
}
} // namespace messages

View file

@ -30,7 +30,7 @@ namespace messages
class Emote : public Deserializable
{
public:
void deserialize(const QJsonObject &obj) override;
void deserialize(const QJsonObject &obj) override;
};
} // namespace messages
} // namespace events

View file

@ -29,46 +29,46 @@ namespace events
namespace messages
{
struct FileInfo {
int size;
int size;
QString mimetype;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
QString mimetype;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
};
class File : public Deserializable
{
public:
inline QString url() const;
inline QString filename() const;
inline QString url() const;
inline QString filename() const;
inline FileInfo info() const;
inline FileInfo info() const;
void deserialize(const QJsonObject &object) override;
void deserialize(const QJsonObject &object) override;
private:
QString url_;
QString filename_;
QString url_;
QString filename_;
FileInfo info_;
FileInfo info_;
};
inline QString
File::filename() const
{
return filename_;
return filename_;
}
inline QString
File::url() const
{
return url_;
return url_;
}
inline FileInfo
File::info() const
{
return info_;
return info_;
}
} // namespace messages

View file

@ -29,38 +29,38 @@ namespace events
namespace messages
{
struct ImageInfo {
int h;
int w;
int size;
int h;
int w;
int size;
QString mimetype;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
QString mimetype;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
};
class Image : public Deserializable
{
public:
inline QString url() const;
inline ImageInfo info() const;
inline QString url() const;
inline ImageInfo info() const;
void deserialize(const QJsonObject &object) override;
void deserialize(const QJsonObject &object) override;
private:
QString url_;
ImageInfo info_;
QString url_;
ImageInfo info_;
};
inline QString
Image::url() const
{
return url_;
return url_;
}
inline ImageInfo
Image::info() const
{
return info_;
return info_;
}
} // namespace messages

View file

@ -29,34 +29,34 @@ namespace events
namespace messages
{
struct LocationInfo {
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
};
class Location : public Deserializable
{
public:
inline QString geoUri() const;
inline LocationInfo info() const;
inline QString geoUri() const;
inline LocationInfo info() const;
void deserialize(const QJsonObject &object) override;
void deserialize(const QJsonObject &object) override;
private:
QString geo_uri_;
QString geo_uri_;
LocationInfo info_;
LocationInfo info_;
};
inline QString
Location::geoUri() const
{
return geo_uri_;
return geo_uri_;
}
inline LocationInfo
Location::info() const
{
return info_;
return info_;
}
} // namespace messages

View file

@ -30,7 +30,7 @@ namespace messages
class Notice : public Deserializable
{
public:
void deserialize(const QJsonObject &obj) override;
void deserialize(const QJsonObject &obj) override;
};
} // namespace messages
} // namespace events

View file

@ -30,7 +30,7 @@ namespace messages
class Text : public Deserializable
{
public:
void deserialize(const QJsonObject &obj) override;
void deserialize(const QJsonObject &obj) override;
};
} // namespace messages
} // namespace events

View file

@ -29,39 +29,39 @@ namespace events
namespace messages
{
struct VideoInfo {
int h;
int w;
int size;
int duration;
int h;
int w;
int size;
int duration;
QString mimetype;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
QString mimetype;
QString thumbnail_url;
ThumbnailInfo thumbnail_info;
};
class Video : public Deserializable
{
public:
inline QString url() const;
inline VideoInfo info() const;
inline QString url() const;
inline VideoInfo info() const;
void deserialize(const QJsonObject &object) override;
void deserialize(const QJsonObject &object) override;
private:
QString url_;
VideoInfo info_;
QString url_;
VideoInfo info_;
};
inline QString
Video::url() const
{
return url_;
return url_;
}
inline VideoInfo
Video::info() const
{
return info_;
return info_;
}
} // namespace messages

View file

@ -9,40 +9,40 @@
class Avatar : public QWidget
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
public:
explicit Avatar(QWidget *parent = 0);
~Avatar();
explicit Avatar(QWidget *parent = 0);
~Avatar();
void setBackgroundColor(const QColor &color);
void setIcon(const QIcon &icon);
void setImage(const QImage &image);
void setLetter(const QChar &letter);
void setSize(int size);
void setTextColor(const QColor &color);
void setBackgroundColor(const QColor &color);
void setIcon(const QIcon &icon);
void setImage(const QImage &image);
void setLetter(const QChar &letter);
void setSize(int size);
void setTextColor(const QColor &color);
QColor backgroundColor() const;
QColor textColor() const;
int size() const;
QColor backgroundColor() const;
QColor textColor() const;
int size() const;
QSize sizeHint() const override;
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
void init();
void init();
ui::AvatarType type_;
QChar letter_;
QColor background_color_;
QColor text_color_;
QIcon icon_;
QImage image_;
QPixmap pixmap_;
int size_;
ui::AvatarType type_;
QChar letter_;
QColor background_color_;
QColor text_color_;
QIcon icon_;
QImage image_;
QPixmap pixmap_;
int size_;
};

View file

@ -9,55 +9,55 @@
class Badge : public OverlayWidget
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
public:
explicit Badge(QWidget *parent = 0);
explicit Badge(const QIcon &icon, QWidget *parent = 0);
explicit Badge(const QString &text, QWidget *parent = 0);
~Badge();
explicit Badge(QWidget *parent = 0);
explicit Badge(const QIcon &icon, QWidget *parent = 0);
explicit Badge(const QString &text, QWidget *parent = 0);
~Badge();
void setBackgroundColor(const QColor &color);
void setTextColor(const QColor &color);
void setIcon(const QIcon &icon);
void setRelativePosition(const QPointF &pos);
void setRelativePosition(qreal x, qreal y);
void setRelativeXPosition(qreal x);
void setRelativeYPosition(qreal y);
void setText(const QString &text);
void setDiameter(int diameter);
void setBackgroundColor(const QColor &color);
void setTextColor(const QColor &color);
void setIcon(const QIcon &icon);
void setRelativePosition(const QPointF &pos);
void setRelativePosition(qreal x, qreal y);
void setRelativeXPosition(qreal x);
void setRelativeYPosition(qreal y);
void setText(const QString &text);
void setDiameter(int diameter);
QIcon icon() const;
QString text() const;
QColor backgroundColor() const;
QColor textColor() const;
QPointF relativePosition() const;
QSize sizeHint() const override;
qreal relativeXPosition() const;
qreal relativeYPosition() const;
QIcon icon() const;
QString text() const;
QColor backgroundColor() const;
QColor textColor() const;
QPointF relativePosition() const;
QSize sizeHint() const override;
qreal relativeXPosition() const;
qreal relativeYPosition() const;
int diameter() const;
int diameter() const;
protected:
void paintEvent(QPaintEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
void init();
void init();
QColor background_color_;
QColor text_color_;
QColor background_color_;
QColor text_color_;
QIcon icon_;
QSize size_;
QString text_;
QIcon icon_;
QSize size_;
QString text_;
int padding_;
int diameter_;
int padding_;
int diameter_;
qreal x_;
qreal y_;
qreal x_;
qreal y_;
};

View file

@ -9,112 +9,112 @@ class CircularProgressDelegate;
class CircularProgress : public QProgressBar
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(qreal lineWidth WRITE setLineWidth READ lineWidth)
Q_PROPERTY(qreal size WRITE setSize READ size)
Q_PROPERTY(QColor color WRITE setColor READ color)
Q_PROPERTY(qreal lineWidth WRITE setLineWidth READ lineWidth)
Q_PROPERTY(qreal size WRITE setSize READ size)
Q_PROPERTY(QColor color WRITE setColor READ color)
public:
explicit CircularProgress(QWidget *parent = nullptr);
~CircularProgress();
explicit CircularProgress(QWidget *parent = nullptr);
~CircularProgress();
void setProgressType(ui::ProgressType type);
void setLineWidth(qreal width);
void setSize(int size);
void setColor(const QColor &color);
void setProgressType(ui::ProgressType type);
void setLineWidth(qreal width);
void setSize(int size);
void setColor(const QColor &color);
ui::ProgressType progressType() const;
qreal lineWidth() const;
int size() const;
QColor color() const;
ui::ProgressType progressType() const;
qreal lineWidth() const;
int size() const;
QColor color() const;
QSize sizeHint() const override;
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
CircularProgressDelegate *delegate_;
CircularProgressDelegate *delegate_;
ui::ProgressType progress_type_;
ui::ProgressType progress_type_;
QColor color_;
QColor color_;
// Circle width.
qreal width_;
// Circle width.
qreal width_;
// Circle radius.
int size_;
// Circle radius.
int size_;
// Animation duration.
int duration_;
// Animation duration.
int duration_;
};
class CircularProgressDelegate : public QObject
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(qreal dashOffset WRITE setDashOffset READ dashOffset)
Q_PROPERTY(qreal dashLength WRITE setDashLength READ dashLength)
Q_PROPERTY(int angle WRITE setAngle READ angle)
Q_PROPERTY(qreal dashOffset WRITE setDashOffset READ dashOffset)
Q_PROPERTY(qreal dashLength WRITE setDashLength READ dashLength)
Q_PROPERTY(int angle WRITE setAngle READ angle)
public:
explicit CircularProgressDelegate(CircularProgress *parent);
~CircularProgressDelegate();
explicit CircularProgressDelegate(CircularProgress *parent);
~CircularProgressDelegate();
inline void setDashOffset(qreal offset);
inline void setDashLength(qreal length);
inline void setAngle(int angle);
inline void setDashOffset(qreal offset);
inline void setDashLength(qreal length);
inline void setAngle(int angle);
inline qreal dashOffset() const;
inline qreal dashLength() const;
inline int angle() const;
inline qreal dashOffset() const;
inline qreal dashLength() const;
inline int angle() const;
private:
CircularProgress *const progress_;
CircularProgress *const progress_;
qreal dash_offset_;
qreal dash_length_;
qreal dash_offset_;
qreal dash_length_;
int angle_;
int angle_;
};
inline void
CircularProgressDelegate::setDashOffset(qreal offset)
{
dash_offset_ = offset;
progress_->update();
dash_offset_ = offset;
progress_->update();
}
inline void
CircularProgressDelegate::setDashLength(qreal length)
{
dash_length_ = length;
progress_->update();
dash_length_ = length;
progress_->update();
}
inline void
CircularProgressDelegate::setAngle(int angle)
{
angle_ = angle;
progress_->update();
angle_ = angle;
progress_->update();
}
inline qreal
CircularProgressDelegate::dashOffset() const
{
return dash_offset_;
return dash_offset_;
}
inline qreal
CircularProgressDelegate::dashLength() const
{
return dash_length_;
return dash_length_;
}
inline int
CircularProgressDelegate::angle() const
{
return angle_;
return angle_;
}

View file

@ -7,97 +7,105 @@
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);
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);
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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
}
// Widget
painter.setBrush(QBrush("#FFFFFF"));
painter.setRenderHint(QPainter::Antialiasing);
painter.drawRoundRect(
QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)),
radius,
radius);
}
};

View file

@ -12,167 +12,174 @@ class FlatButton;
class FlatButtonStateMachine : public QStateMachine
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
Q_PROPERTY(qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
Q_PROPERTY(
qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
public:
explicit FlatButtonStateMachine(FlatButton *parent);
~FlatButtonStateMachine();
explicit FlatButtonStateMachine(FlatButton *parent);
~FlatButtonStateMachine();
void setOverlayOpacity(qreal opacity);
void setCheckedOverlayProgress(qreal opacity);
void setOverlayOpacity(qreal opacity);
void setCheckedOverlayProgress(qreal opacity);
inline qreal overlayOpacity() const;
inline qreal checkedOverlayProgress() const;
inline qreal overlayOpacity() const;
inline qreal checkedOverlayProgress() const;
void startAnimations();
void setupProperties();
void updateCheckedStatus();
void startAnimations();
void setupProperties();
void updateCheckedStatus();
signals:
void buttonPressed();
void buttonChecked();
void buttonUnchecked();
void buttonPressed();
void buttonChecked();
void buttonUnchecked();
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
bool eventFilter(QObject *watched, QEvent *event) override;
private:
void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
void addTransition(QObject *object, QEvent::Type eventType, QState *fromState, QState *toState);
void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
void addTransition(QObject *object,
QEvent::Type eventType,
QState *fromState,
QState *toState);
void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
FlatButton *const button_;
FlatButton *const button_;
QState *const top_level_state_;
QState *const config_state_;
QState *const checkable_state_;
QState *const checked_state_;
QState *const unchecked_state_;
QState *const neutral_state_;
QState *const neutral_focused_state_;
QState *const hovered_state_;
QState *const hovered_focused_state_;
QState *const pressed_state_;
QState *const top_level_state_;
QState *const config_state_;
QState *const checkable_state_;
QState *const checked_state_;
QState *const unchecked_state_;
QState *const neutral_state_;
QState *const neutral_focused_state_;
QState *const hovered_state_;
QState *const hovered_focused_state_;
QState *const pressed_state_;
qreal overlay_opacity_;
qreal checked_overlay_progress_;
qreal overlay_opacity_;
qreal checked_overlay_progress_;
bool was_checked_;
bool was_checked_;
};
inline qreal
FlatButtonStateMachine::overlayOpacity() const
{
return overlay_opacity_;
return overlay_opacity_;
}
inline qreal
FlatButtonStateMachine::checkedOverlayProgress() const
{
return checked_overlay_progress_;
return checked_overlay_progress_;
}
class FlatButton : public QPushButton
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ disabledForegroundColor)
Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ disabledBackgroundColor)
Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ
disabledForegroundColor)
Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ
disabledBackgroundColor)
Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
public:
explicit FlatButton(QWidget *parent = 0, ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
explicit FlatButton(const QString &text,
QWidget *parent = 0,
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
FlatButton(const QString &text,
ui::Role role,
QWidget *parent = 0,
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
~FlatButton();
explicit FlatButton(QWidget *parent = 0,
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
explicit FlatButton(const QString &text,
QWidget *parent = 0,
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
FlatButton(const QString &text,
ui::Role role,
QWidget *parent = 0,
ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
~FlatButton();
void applyPreset(ui::ButtonPreset preset);
void applyPreset(ui::ButtonPreset preset);
void setBackgroundColor(const QColor &color);
void setBackgroundMode(Qt::BGMode mode);
void setBaseOpacity(qreal opacity);
void setCheckable(bool value);
void setCornerRadius(qreal radius);
void setDisabledBackgroundColor(const QColor &color);
void setDisabledForegroundColor(const QColor &color);
void setFixedRippleRadius(qreal radius);
void setFontSize(qreal size);
void setForegroundColor(const QColor &color);
void setHasFixedRippleRadius(bool value);
void setIconPlacement(ui::ButtonIconPlacement placement);
void setOverlayColor(const QColor &color);
void setOverlayStyle(ui::OverlayStyle style);
void setRippleStyle(ui::RippleStyle style);
void setRole(ui::Role role);
void setBackgroundColor(const QColor &color);
void setBackgroundMode(Qt::BGMode mode);
void setBaseOpacity(qreal opacity);
void setCheckable(bool value);
void setCornerRadius(qreal radius);
void setDisabledBackgroundColor(const QColor &color);
void setDisabledForegroundColor(const QColor &color);
void setFixedRippleRadius(qreal radius);
void setFontSize(qreal size);
void setForegroundColor(const QColor &color);
void setHasFixedRippleRadius(bool value);
void setIconPlacement(ui::ButtonIconPlacement placement);
void setOverlayColor(const QColor &color);
void setOverlayStyle(ui::OverlayStyle style);
void setRippleStyle(ui::RippleStyle style);
void setRole(ui::Role role);
QColor foregroundColor() const;
QColor backgroundColor() const;
QColor overlayColor() const;
QColor disabledForegroundColor() const;
QColor disabledBackgroundColor() const;
QColor foregroundColor() const;
QColor backgroundColor() const;
QColor overlayColor() const;
QColor disabledForegroundColor() const;
QColor disabledBackgroundColor() const;
qreal fontSize() const;
qreal cornerRadius() const;
qreal baseOpacity() const;
qreal fontSize() const;
qreal cornerRadius() const;
qreal baseOpacity() const;
bool hasFixedRippleRadius() const;
bool hasFixedRippleRadius() const;
ui::Role role() const;
ui::OverlayStyle overlayStyle() const;
ui::RippleStyle rippleStyle() const;
ui::ButtonIconPlacement iconPlacement() const;
ui::Role role() const;
ui::OverlayStyle overlayStyle() const;
ui::RippleStyle rippleStyle() const;
ui::ButtonIconPlacement iconPlacement() const;
Qt::BGMode backgroundMode() const;
Qt::BGMode backgroundMode() const;
QSize sizeHint() const override;
QSize sizeHint() const override;
protected:
int IconPadding = 0;
int IconPadding = 0;
void checkStateSet() override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
void checkStateSet() override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void paintEvent(QPaintEvent *event) override;
virtual void paintBackground(QPainter *painter);
virtual void paintForeground(QPainter *painter);
virtual void updateClipPath();
virtual void paintBackground(QPainter *painter);
virtual void paintForeground(QPainter *painter);
virtual void updateClipPath();
void init();
void init();
private:
RippleOverlay *ripple_overlay_;
FlatButtonStateMachine *state_machine_;
RippleOverlay *ripple_overlay_;
FlatButtonStateMachine *state_machine_;
ui::Role role_;
ui::RippleStyle ripple_style_;
ui::ButtonIconPlacement icon_placement_;
ui::OverlayStyle overlay_style_;
ui::Role role_;
ui::RippleStyle ripple_style_;
ui::ButtonIconPlacement icon_placement_;
ui::OverlayStyle overlay_style_;
Qt::BGMode bg_mode_;
Qt::BGMode bg_mode_;
QColor background_color_;
QColor foreground_color_;
QColor overlay_color_;
QColor disabled_color_;
QColor disabled_background_color_;
QColor background_color_;
QColor foreground_color_;
QColor overlay_color_;
QColor disabled_color_;
QColor disabled_background_color_;
qreal fixed_ripple_radius_;
qreal corner_radius_;
qreal base_opacity_;
qreal font_size_;
qreal fixed_ripple_radius_;
qreal corner_radius_;
qreal base_opacity_;
qreal font_size_;
bool use_fixed_ripple_radius_;
bool use_fixed_ripple_radius_;
};

View file

@ -7,24 +7,26 @@
class Menu : public QMenu
{
public:
Menu(QWidget *parent = nullptr)
: QMenu(parent)
{
QFont font;
font.setPixelSize(conf::fontSize);
Menu(QWidget *parent = nullptr)
: QMenu(parent)
{
QFont font;
font.setPixelSize(conf::fontSize);
setFont(font);
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); }");
};
setFont(font);
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);
void leaveEvent(QEvent *e)
{
Q_UNUSED(e);
hide();
}
hide();
}
};

View file

@ -26,35 +26,35 @@
class OverlayModal : public OverlayWidget
{
public:
explicit OverlayModal(QWidget *parent, QWidget *content);
explicit OverlayModal(QWidget *parent, QWidget *content);
void fadeIn();
void fadeOut();
void fadeIn();
void fadeOut();
public:
inline void setDuration(int duration);
inline void setColor(QColor color);
inline void setDuration(int duration);
inline void setColor(QColor color);
protected:
void paintEvent(QPaintEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
int duration_;
QColor color_;
int duration_;
QColor color_;
QGraphicsOpacityEffect *opacity_;
QPropertyAnimation *animation_;
QGraphicsOpacityEffect *opacity_;
QPropertyAnimation *animation_;
};
inline void
OverlayModal::setDuration(int duration)
{
duration_ = duration;
animation_->setDuration(duration_);
duration_ = duration;
animation_->setDuration(duration_);
}
inline void
OverlayModal::setColor(QColor color)
{
color_ = color;
color_ = color;
}

View file

@ -5,14 +5,14 @@
class OverlayWidget : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
explicit OverlayWidget(QWidget *parent = nullptr);
explicit OverlayWidget(QWidget *parent = nullptr);
protected:
bool event(QEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
bool event(QEvent *event) override;
bool eventFilter(QObject *obj, QEvent *event) override;
QRect overlayGeometry() const;
QRect overlayGeometry() const;
};

View file

@ -8,21 +8,21 @@
class RaisedButton : public FlatButton
{
Q_OBJECT
Q_OBJECT
public:
explicit RaisedButton(QWidget *parent = 0);
explicit RaisedButton(const QString &text, QWidget *parent = 0);
~RaisedButton();
explicit RaisedButton(QWidget *parent = 0);
explicit RaisedButton(const QString &text, QWidget *parent = 0);
~RaisedButton();
protected:
bool event(QEvent *event) override;
bool event(QEvent *event) override;
private:
void init();
void init();
QStateMachine *shadow_state_machine_;
QState *normal_state_;
QState *pressed_state_;
QGraphicsDropShadowEffect *effect_;
QStateMachine *shadow_state_machine_;
QState *normal_state_;
QState *pressed_state_;
QGraphicsDropShadowEffect *effect_;
};

View file

@ -10,137 +10,137 @@ class RippleOverlay;
class Ripple : public QParallelAnimationGroup
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(qreal radius WRITE setRadius READ radius)
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
Q_PROPERTY(qreal radius WRITE setRadius READ radius)
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
public:
explicit Ripple(const QPoint &center, QObject *parent = 0);
Ripple(const QPoint &center, RippleOverlay *overlay, QObject *parent = 0);
~Ripple();
explicit Ripple(const QPoint &center, QObject *parent = 0);
Ripple(const QPoint &center, RippleOverlay *overlay, QObject *parent = 0);
~Ripple();
inline void setOverlay(RippleOverlay *overlay);
inline void setOverlay(RippleOverlay *overlay);
void setRadius(qreal radius);
void setOpacity(qreal opacity);
void setColor(const QColor &color);
void setBrush(const QBrush &brush);
void setRadius(qreal radius);
void setOpacity(qreal opacity);
void setColor(const QColor &color);
void setBrush(const QBrush &brush);
inline qreal radius() const;
inline qreal opacity() const;
inline QColor color() const;
inline QBrush brush() const;
inline QPoint center() const;
inline qreal radius() const;
inline qreal opacity() const;
inline QColor color() const;
inline QBrush brush() const;
inline QPoint center() const;
inline QPropertyAnimation *radiusAnimation() const;
inline QPropertyAnimation *opacityAnimation() const;
inline QPropertyAnimation *radiusAnimation() const;
inline QPropertyAnimation *opacityAnimation() const;
inline void setOpacityStartValue(qreal value);
inline void setOpacityEndValue(qreal value);
inline void setRadiusStartValue(qreal value);
inline void setRadiusEndValue(qreal value);
inline void setDuration(int msecs);
inline void setOpacityStartValue(qreal value);
inline void setOpacityEndValue(qreal value);
inline void setRadiusStartValue(qreal value);
inline void setRadiusEndValue(qreal value);
inline void setDuration(int msecs);
protected slots:
void destroy();
void destroy();
private:
Q_DISABLE_COPY(Ripple)
Q_DISABLE_COPY(Ripple)
QPropertyAnimation *animate(const QByteArray &property,
const QEasingCurve &easing = QEasingCurve::OutQuad,
int duration = 800);
QPropertyAnimation *animate(const QByteArray &property,
const QEasingCurve &easing = QEasingCurve::OutQuad,
int duration = 800);
void init();
void init();
RippleOverlay *overlay_;
RippleOverlay *overlay_;
QPropertyAnimation *const radius_anim_;
QPropertyAnimation *const opacity_anim_;
QPropertyAnimation *const radius_anim_;
QPropertyAnimation *const opacity_anim_;
qreal radius_;
qreal opacity_;
qreal radius_;
qreal opacity_;
QPoint center_;
QBrush brush_;
QPoint center_;
QBrush brush_;
};
inline void
Ripple::setOverlay(RippleOverlay *overlay)
{
overlay_ = overlay;
overlay_ = overlay;
}
inline qreal
Ripple::radius() const
{
return radius_;
return radius_;
}
inline qreal
Ripple::opacity() const
{
return opacity_;
return opacity_;
}
inline QColor
Ripple::color() const
{
return brush_.color();
return brush_.color();
}
inline QBrush
Ripple::brush() const
{
return brush_;
return brush_;
}
inline QPoint
Ripple::center() const
{
return center_;
return center_;
}
inline QPropertyAnimation *
Ripple::radiusAnimation() const
{
return radius_anim_;
return radius_anim_;
}
inline QPropertyAnimation *
Ripple::opacityAnimation() const
{
return opacity_anim_;
return opacity_anim_;
}
inline void
Ripple::setOpacityStartValue(qreal value)
{
opacity_anim_->setStartValue(value);
opacity_anim_->setStartValue(value);
}
inline void
Ripple::setOpacityEndValue(qreal value)
{
opacity_anim_->setEndValue(value);
opacity_anim_->setEndValue(value);
}
inline void
Ripple::setRadiusStartValue(qreal value)
{
radius_anim_->setStartValue(value);
radius_anim_->setStartValue(value);
}
inline void
Ripple::setRadiusEndValue(qreal value)
{
radius_anim_->setEndValue(value);
radius_anim_->setEndValue(value);
}
inline void
Ripple::setDuration(int msecs)
{
radius_anim_->setDuration(msecs);
opacity_anim_->setDuration(msecs);
radius_anim_->setDuration(msecs);
opacity_anim_->setDuration(msecs);
}

View file

@ -8,51 +8,51 @@ class Ripple;
class RippleOverlay : public OverlayWidget
{
Q_OBJECT
Q_OBJECT
public:
explicit RippleOverlay(QWidget *parent = 0);
~RippleOverlay();
explicit RippleOverlay(QWidget *parent = 0);
~RippleOverlay();
void addRipple(Ripple *ripple);
void addRipple(const QPoint &position, qreal radius = 300);
void addRipple(Ripple *ripple);
void addRipple(const QPoint &position, qreal radius = 300);
void removeRipple(Ripple *ripple);
void removeRipple(Ripple *ripple);
inline void setClipping(bool enable);
inline bool hasClipping() const;
inline void setClipping(bool enable);
inline bool hasClipping() const;
inline void setClipPath(const QPainterPath &path);
inline void setClipPath(const QPainterPath &path);
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(RippleOverlay)
Q_DISABLE_COPY(RippleOverlay)
void paintRipple(QPainter *painter, Ripple *ripple);
void paintRipple(QPainter *painter, Ripple *ripple);
QList<Ripple *> ripples_;
QPainterPath clip_path_;
bool use_clip_;
QList<Ripple *> ripples_;
QPainterPath clip_path_;
bool use_clip_;
};
inline void
RippleOverlay::setClipping(bool enable)
{
use_clip_ = enable;
update();
use_clip_ = enable;
update();
}
inline bool
RippleOverlay::hasClipping() const
{
return use_clip_;
return use_clip_;
}
inline void
RippleOverlay::setClipPath(const QPainterPath &path)
{
clip_path_ = path;
update();
clip_path_ = path;
update();
}

View file

@ -25,29 +25,29 @@
class ScrollBar : public QScrollBar
{
Q_OBJECT
Q_OBJECT
public:
ScrollBar(QScrollArea *area, QWidget *parent = nullptr);
ScrollBar(QScrollArea *area, QWidget *parent = nullptr);
void fadeIn();
void fadeOut();
void fadeIn();
void fadeOut();
protected:
void paintEvent(QPaintEvent *e) override;
void sliderChange(SliderChange change) override;
void paintEvent(QPaintEvent *e) override;
void sliderChange(SliderChange change) override;
private:
int roundRadius_ = 4;
int handleWidth_ = 7;
int minHandleHeight_ = 20;
bool isActive;
int roundRadius_ = 4;
int handleWidth_ = 7;
int minHandleHeight_ = 20;
bool isActive;
const int AnimationDuration = 300;
const int Padding = 4;
const int AnimationDuration = 300;
const int Padding = 4;
QGraphicsOpacityEffect *eff;
QTimer hideTimer_;
QGraphicsOpacityEffect *eff;
QTimer hideTimer_;
QScrollArea *area_;
QRect handle_;
QScrollArea *area_;
QRect handle_;
};

View file

@ -13,163 +13,163 @@ class TextFieldStateMachine;
class TextField : public QLineEdit
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
public:
explicit TextField(QWidget *parent = 0);
~TextField();
explicit TextField(QWidget *parent = 0);
~TextField();
void setInkColor(const QColor &color);
void setBackgroundColor(const QColor &color);
void setLabel(const QString &label);
void setLabelColor(const QColor &color);
void setLabelFontSize(qreal size);
void setShowLabel(bool value);
void setTextColor(const QColor &color);
void setUnderlineColor(const QColor &color);
void setInkColor(const QColor &color);
void setBackgroundColor(const QColor &color);
void setLabel(const QString &label);
void setLabelColor(const QColor &color);
void setLabelFontSize(qreal size);
void setShowLabel(bool value);
void setTextColor(const QColor &color);
void setUnderlineColor(const QColor &color);
QColor inkColor() const;
QColor labelColor() const;
QColor textColor() const;
QColor underlineColor() const;
QColor backgroundColor() const;
QString label() const;
bool hasLabel() const;
qreal labelFontSize() const;
QColor inkColor() const;
QColor labelColor() const;
QColor textColor() const;
QColor underlineColor() const;
QColor backgroundColor() const;
QString label() const;
bool hasLabel() const;
qreal labelFontSize() const;
protected:
bool event(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
bool event(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
void init();
void init();
QColor ink_color_;
QColor background_color_;
QColor label_color_;
QColor text_color_;
QColor underline_color_;
QString label_text_;
TextFieldLabel *label_;
TextFieldStateMachine *state_machine_;
bool show_label_;
qreal label_font_size_;
QColor ink_color_;
QColor background_color_;
QColor label_color_;
QColor text_color_;
QColor underline_color_;
QString label_text_;
TextFieldLabel *label_;
TextFieldStateMachine *state_machine_;
bool show_label_;
qreal label_font_size_;
};
class TextFieldLabel : public QWidget
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(qreal scale WRITE setScale READ scale)
Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
Q_PROPERTY(QColor color WRITE setColor READ color)
Q_PROPERTY(qreal scale WRITE setScale READ scale)
Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
Q_PROPERTY(QColor color WRITE setColor READ color)
public:
TextFieldLabel(TextField *parent);
~TextFieldLabel();
TextFieldLabel(TextField *parent);
~TextFieldLabel();
inline void setColor(const QColor &color);
inline void setOffset(const QPointF &pos);
inline void setScale(qreal scale);
inline void setColor(const QColor &color);
inline void setOffset(const QPointF &pos);
inline void setScale(qreal scale);
inline QColor color() const;
inline QPointF offset() const;
inline qreal scale() const;
inline QColor color() const;
inline QPointF offset() const;
inline qreal scale() const;
protected:
void paintEvent(QPaintEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
TextField *const text_field_;
TextField *const text_field_;
QColor color_;
qreal scale_;
qreal x_;
qreal y_;
QColor color_;
qreal scale_;
qreal x_;
qreal y_;
};
inline void
TextFieldLabel::setColor(const QColor &color)
{
color_ = color;
update();
color_ = color;
update();
}
inline void
TextFieldLabel::setOffset(const QPointF &pos)
{
x_ = pos.x();
y_ = pos.y();
update();
x_ = pos.x();
y_ = pos.y();
update();
}
inline void
TextFieldLabel::setScale(qreal scale)
{
scale_ = scale;
update();
scale_ = scale;
update();
}
inline QPointF
TextFieldLabel::offset() const
{
return QPointF(x_, y_);
return QPointF(x_, y_);
}
inline qreal
TextFieldLabel::scale() const
{
return scale_;
return scale_;
}
inline QColor
TextFieldLabel::color() const
{
return color_;
return color_;
}
class TextFieldStateMachine : public QStateMachine
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY(qreal progress WRITE setProgress READ progress)
Q_PROPERTY(qreal progress WRITE setProgress READ progress)
public:
TextFieldStateMachine(TextField *parent);
~TextFieldStateMachine();
TextFieldStateMachine(TextField *parent);
~TextFieldStateMachine();
inline void setProgress(qreal progress);
void setLabel(TextFieldLabel *label);
inline void setProgress(qreal progress);
void setLabel(TextFieldLabel *label);
inline qreal progress() const;
inline qreal progress() const;
public slots:
void setupProperties();
void setupProperties();
private:
QPropertyAnimation *color_anim_;
QPropertyAnimation *offset_anim_;
QPropertyAnimation *color_anim_;
QPropertyAnimation *offset_anim_;
QState *focused_state_;
QState *normal_state_;
QState *focused_state_;
QState *normal_state_;
TextField *text_field_;
TextFieldLabel *label_;
TextField *text_field_;
TextFieldLabel *label_;
qreal progress_;
qreal progress_;
};
inline void
TextFieldStateMachine::setProgress(qreal progress)
{
progress_ = progress;
text_field_->update();
progress_ = progress;
text_field_->update();
}
inline qreal
TextFieldStateMachine::progress() const
{
return progress_;
return progress_;
}

View file

@ -10,7 +10,7 @@ enum class AvatarType { Icon, Image, Letter };
namespace sidebar
{
static const int SmallSize = 60;
static const int SmallSize = 60;
static const int NormalSize = 300;
}
// Default font size.
@ -32,35 +32,35 @@ enum class ButtonIconPlacement { LeftIcon, RightIcon };
enum class ProgressType { DeterminateProgress, IndeterminateProgress };
enum class Color {
Black,
BrightWhite,
FadedWhite,
MediumWhite,
DarkGreen,
LightGreen,
BrightGreen,
Gray,
Red,
Blue,
Transparent
Black,
BrightWhite,
FadedWhite,
MediumWhite,
DarkGreen,
LightGreen,
BrightGreen,
Gray,
Red,
Blue,
Transparent
};
} // namespace ui
class Theme : public QObject
{
Q_OBJECT
Q_OBJECT
public:
explicit Theme(QObject *parent = 0);
~Theme();
explicit Theme(QObject *parent = 0);
~Theme();
QColor getColor(const QString &key) const;
QColor getColor(const QString &key) const;
void setColor(const QString &key, const QColor &color);
void setColor(const QString &key, ui::Color color);
void setColor(const QString &key, const QColor &color);
void setColor(const QString &key, ui::Color color);
private:
QColor rgba(int r, int g, int b, qreal a) const;
QColor rgba(int r, int g, int b, qreal a) const;
QHash<QString, QColor> colors_;
QHash<QString, QColor> colors_;
};

View file

@ -6,26 +6,26 @@
class ThemeManager : public QCommonStyle
{
Q_OBJECT
Q_OBJECT
public:
inline static ThemeManager &instance();
inline static ThemeManager &instance();
void setTheme(Theme *theme);
QColor themeColor(const QString &key) const;
void setTheme(Theme *theme);
QColor themeColor(const QString &key) const;
private:
ThemeManager();
ThemeManager();
ThemeManager(ThemeManager const &);
void operator=(ThemeManager const &);
ThemeManager(ThemeManager const &);
void operator=(ThemeManager const &);
Theme *theme_;
Theme *theme_;
};
inline ThemeManager &
ThemeManager::instance()
{
static ThemeManager instance;
return instance;
static ThemeManager instance;
return instance;
}

View file

@ -26,63 +26,63 @@ QMap<QString, QList<TimelineItem *>> AvatarProvider::toBeResolved_;
void
AvatarProvider::init(QSharedPointer<MatrixClient> client)
{
client_ = client;
client_ = client;
connect(client_.data(), &MatrixClient::userAvatarRetrieved, &AvatarProvider::updateAvatar);
connect(client_.data(), &MatrixClient::userAvatarRetrieved, &AvatarProvider::updateAvatar);
}
void
AvatarProvider::updateAvatar(const QString &uid, const QImage &img)
{
if (toBeResolved_.contains(uid)) {
auto items = toBeResolved_[uid];
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);
// Update all the timeline items with the resolved avatar.
for (const auto item : items)
item->setUserAvatar(img);
toBeResolved_.remove(uid);
}
toBeResolved_.remove(uid);
}
userAvatars_.insert(uid, img);
userAvatars_.insert(uid, img);
}
void
AvatarProvider::resolve(const QString &userId, TimelineItem *item)
{
if (userAvatars_.contains(userId)) {
auto img = userAvatars_[userId];
if (userAvatars_.contains(userId)) {
auto img = userAvatars_[userId];
item->setUserAvatar(img);
item->setUserAvatar(img);
return;
}
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]);
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);
QList<TimelineItem *> timelineItems;
timelineItems.push_back(item);
toBeResolved_.insert(userId, timelineItems);
} else {
toBeResolved_[userId].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);
avatarUrls_.insert(userId, url);
}
void
AvatarProvider::clear()
{
userAvatars_.clear();
avatarUrls_.clear();
toBeResolved_.clear();
userAvatars_.clear();
avatarUrls_.clear();
toBeResolved_.clear();
}

View file

@ -29,5 +29,5 @@ DeserializationException::DeserializationException(const std::string &msg)
const char *
DeserializationException::what() const noexcept
{
return msg_.c_str();
return msg_.c_str();
}

View file

@ -24,60 +24,60 @@
EmojiCategory::EmojiCategory(QString category, QList<Emoji> emoji, QWidget *parent)
: QWidget(parent)
{
mainLayout_ = new QVBoxLayout(this);
mainLayout_->setMargin(0);
mainLayout_ = new QVBoxLayout(this);
mainLayout_->setMargin(0);
emojiListView_ = new QListView();
itemModel_ = new QStandardItemModel(this);
emojiListView_ = new QListView();
itemModel_ = new QStandardItemModel(this);
delegate_ = new EmojiItemDelegate(this);
data_ = new Emoji;
delegate_ = new EmojiItemDelegate(this);
data_ = new Emoji;
emojiListView_->setItemDelegate(delegate_);
emojiListView_->setSpacing(5);
emojiListView_->setModel(itemModel_);
emojiListView_->setViewMode(QListView::IconMode);
emojiListView_->setFlow(QListView::LeftToRight);
emojiListView_->setResizeMode(QListView::Adjust);
emojiListView_->verticalScrollBar()->setEnabled(false);
emojiListView_->horizontalScrollBar()->setEnabled(false);
emojiListView_->setItemDelegate(delegate_);
emojiListView_->setSpacing(5);
emojiListView_->setModel(itemModel_);
emojiListView_->setViewMode(QListView::IconMode);
emojiListView_->setFlow(QListView::LeftToRight);
emojiListView_->setResizeMode(QListView::Adjust);
emojiListView_->verticalScrollBar()->setEnabled(false);
emojiListView_->horizontalScrollBar()->setEnabled(false);
const int cols = 7;
const int rows = emoji.size() / 7;
const int cols = 7;
const int rows = emoji.size() / 7;
// TODO: Be precise here. Take the parent into consideration.
emojiListView_->setFixedSize(cols * 50 + 20, rows * 50 + 20);
emojiListView_->setGridSize(QSize(50, 50));
emojiListView_->setDragEnabled(false);
emojiListView_->setEditTriggers(QAbstractItemView::NoEditTriggers);
// TODO: Be precise here. Take the parent into consideration.
emojiListView_->setFixedSize(cols * 50 + 20, rows * 50 + 20);
emojiListView_->setGridSize(QSize(50, 50));
emojiListView_->setDragEnabled(false);
emojiListView_->setEditTriggers(QAbstractItemView::NoEditTriggers);
for (const auto &e : emoji) {
data_->unicode = e.unicode;
for (const auto &e : emoji) {
data_->unicode = e.unicode;
auto item = new QStandardItem;
item->setSizeHint(QSize(24, 24));
auto item = new QStandardItem;
item->setSizeHint(QSize(24, 24));
QVariant unicode(data_->unicode);
item->setData(unicode.toString(), Qt::UserRole);
QVariant unicode(data_->unicode);
item->setData(unicode.toString(), Qt::UserRole);
itemModel_->appendRow(item);
}
itemModel_->appendRow(item);
}
QFont font("Open Sans SemiBold");
font.setPixelSize(conf::fontSize);
QFont font("Open Sans SemiBold");
font.setPixelSize(conf::fontSize);
category_ = new QLabel(category, this);
category_->setFont(font);
category_->setStyleSheet("color: #ccc; margin: 20px 0px 15px 8px;");
category_ = new QLabel(category, this);
category_->setFont(font);
category_->setStyleSheet("color: #ccc; margin: 20px 0px 15px 8px;");
auto labelLayout_ = new QHBoxLayout();
labelLayout_->addWidget(category_);
labelLayout_->addStretch(1);
auto labelLayout_ = new QHBoxLayout();
labelLayout_->addWidget(category_);
labelLayout_->addStretch(1);
mainLayout_->addLayout(labelLayout_);
mainLayout_->addWidget(emojiListView_);
mainLayout_->addLayout(labelLayout_);
mainLayout_->addWidget(emojiListView_);
connect(emojiListView_, &QListView::clicked, this, &EmojiCategory::clickIndex);
connect(emojiListView_, &QListView::clicked, this, &EmojiCategory::clickIndex);
}
EmojiCategory::~EmojiCategory()

View file

@ -23,26 +23,28 @@
EmojiItemDelegate::EmojiItemDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
data_ = new Emoji;
data_ = new Emoji;
}
EmojiItemDelegate::~EmojiItemDelegate()
{
delete data_;
delete data_;
}
void
EmojiItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
EmojiItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Q_UNUSED(index);
Q_UNUSED(index);
QStyleOptionViewItem viewOption(option);
QStyleOptionViewItem viewOption(option);
auto emoji = index.data(Qt::UserRole).toString();
auto emoji = index.data(Qt::UserRole).toString();
QFont font("Emoji One");
font.setPixelSize(19);
QFont font("Emoji One");
font.setPixelSize(19);
painter->setFont(font);
painter->drawText(viewOption.rect, Qt::AlignCenter, emoji);
painter->setFont(font);
painter->drawText(viewOption.rect, Qt::AlignCenter, emoji);
}

View file

@ -34,225 +34,238 @@ EmojiPanel::EmojiPanel(QWidget *parent)
, animationDuration_{ 100 }
, categoryIconSize_{ 20 }
{
setStyleSheet("QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}"
"QScrollBar:vertical { background-color: #f8fbfe; width: 8px; margin: 0px 2px 0 2px; }"
"QScrollBar::handle:vertical { background-color: #d6dde3; min-height: 20px; }"
"QScrollBar::add-line:vertical { border: none; background: none; }"
"QScrollBar::sub-line:vertical { border: none; background: none; }");
setStyleSheet(
"QWidget {background: #f8fbfe; color: #e8e8e8; border: none;}"
"QScrollBar:vertical { background-color: #f8fbfe; width: 8px; margin: 0px 2px 0 2px; }"
"QScrollBar::handle:vertical { background-color: #d6dde3; min-height: 20px; }"
"QScrollBar::add-line:vertical { border: none; background: none; }"
"QScrollBar::sub-line:vertical { border: none; background: none; }");
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_ShowWithoutActivating, true);
setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_ShowWithoutActivating, true);
setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
auto mainWidget = new QWidget(this);
mainWidget->setMaximumSize(width_, height_);
auto mainWidget = new QWidget(this);
mainWidget->setMaximumSize(width_, height_);
auto topLayout = new QVBoxLayout(this);
topLayout->addWidget(mainWidget);
topLayout->setMargin(shadowMargin_);
auto topLayout = new QVBoxLayout(this);
topLayout->addWidget(mainWidget);
topLayout->setMargin(shadowMargin_);
auto contentLayout = new QVBoxLayout(mainWidget);
contentLayout->setMargin(0);
auto contentLayout = new QVBoxLayout(mainWidget);
contentLayout->setMargin(0);
auto emojiCategories = new QFrame(mainWidget);
emojiCategories->setStyleSheet("background-color: #f2f2f2");
auto emojiCategories = new QFrame(mainWidget);
emojiCategories->setStyleSheet("background-color: #f2f2f2");
auto categoriesLayout = new QHBoxLayout(emojiCategories);
categoriesLayout->setSpacing(6);
categoriesLayout->setMargin(5);
auto categoriesLayout = new QHBoxLayout(emojiCategories);
categoriesLayout->setSpacing(6);
categoriesLayout->setMargin(5);
auto peopleCategory = new FlatButton(emojiCategories);
peopleCategory->setIcon(QIcon(":/icons/icons/emoji-categories/people.png"));
peopleCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
peopleCategory->setForegroundColor("gray");
auto peopleCategory = new FlatButton(emojiCategories);
peopleCategory->setIcon(QIcon(":/icons/icons/emoji-categories/people.png"));
peopleCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
peopleCategory->setForegroundColor("gray");
auto natureCategory_ = new FlatButton(emojiCategories);
natureCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png"));
natureCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
natureCategory_->setForegroundColor("gray");
auto natureCategory_ = new FlatButton(emojiCategories);
natureCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/nature.png"));
natureCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
natureCategory_->setForegroundColor("gray");
auto foodCategory_ = new FlatButton(emojiCategories);
foodCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png"));
foodCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
foodCategory_->setForegroundColor("gray");
auto foodCategory_ = new FlatButton(emojiCategories);
foodCategory_->setIcon(QIcon(":/icons/icons/emoji-categories/foods.png"));
foodCategory_->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
foodCategory_->setForegroundColor("gray");
auto activityCategory = new FlatButton(emojiCategories);
activityCategory->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png"));
activityCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
activityCategory->setForegroundColor("gray");
auto activityCategory = new FlatButton(emojiCategories);
activityCategory->setIcon(QIcon(":/icons/icons/emoji-categories/activity.png"));
activityCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
activityCategory->setForegroundColor("gray");
auto travelCategory = new FlatButton(emojiCategories);
travelCategory->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png"));
travelCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
travelCategory->setForegroundColor("gray");
auto travelCategory = new FlatButton(emojiCategories);
travelCategory->setIcon(QIcon(":/icons/icons/emoji-categories/travel.png"));
travelCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
travelCategory->setForegroundColor("gray");
auto objectsCategory = new FlatButton(emojiCategories);
objectsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png"));
objectsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
objectsCategory->setForegroundColor("gray");
auto objectsCategory = new FlatButton(emojiCategories);
objectsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/objects.png"));
objectsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
objectsCategory->setForegroundColor("gray");
auto symbolsCategory = new FlatButton(emojiCategories);
symbolsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png"));
symbolsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
symbolsCategory->setForegroundColor("gray");
auto symbolsCategory = new FlatButton(emojiCategories);
symbolsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/symbols.png"));
symbolsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
symbolsCategory->setForegroundColor("gray");
auto flagsCategory = new FlatButton(emojiCategories);
flagsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png"));
flagsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
flagsCategory->setForegroundColor("gray");
auto flagsCategory = new FlatButton(emojiCategories);
flagsCategory->setIcon(QIcon(":/icons/icons/emoji-categories/flags.png"));
flagsCategory->setIconSize(QSize(categoryIconSize_, categoryIconSize_));
flagsCategory->setForegroundColor("gray");
categoriesLayout->addWidget(peopleCategory);
categoriesLayout->addWidget(natureCategory_);
categoriesLayout->addWidget(foodCategory_);
categoriesLayout->addWidget(activityCategory);
categoriesLayout->addWidget(travelCategory);
categoriesLayout->addWidget(objectsCategory);
categoriesLayout->addWidget(symbolsCategory);
categoriesLayout->addWidget(flagsCategory);
categoriesLayout->addWidget(peopleCategory);
categoriesLayout->addWidget(natureCategory_);
categoriesLayout->addWidget(foodCategory_);
categoriesLayout->addWidget(activityCategory);
categoriesLayout->addWidget(travelCategory);
categoriesLayout->addWidget(objectsCategory);
categoriesLayout->addWidget(symbolsCategory);
categoriesLayout->addWidget(flagsCategory);
scrollArea_ = new QScrollArea(this);
scrollArea_->setWidgetResizable(true);
scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_ = new QScrollArea(this);
scrollArea_->setWidgetResizable(true);
scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
auto scrollWidget = new QWidget(this);
auto scrollLayout = new QVBoxLayout(scrollWidget);
auto scrollWidget = new QWidget(this);
auto scrollLayout = new QVBoxLayout(scrollWidget);
scrollLayout->setMargin(0);
scrollArea_->setWidget(scrollWidget);
scrollLayout->setMargin(0);
scrollArea_->setWidget(scrollWidget);
auto peopleEmoji = new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scrollWidget);
scrollLayout->addWidget(peopleEmoji);
auto peopleEmoji =
new EmojiCategory(tr("Smileys & People"), emoji_provider_.people, scrollWidget);
scrollLayout->addWidget(peopleEmoji);
auto natureEmoji = new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scrollWidget);
scrollLayout->addWidget(natureEmoji);
auto natureEmoji =
new EmojiCategory(tr("Animals & Nature"), emoji_provider_.nature, scrollWidget);
scrollLayout->addWidget(natureEmoji);
auto foodEmoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scrollWidget);
scrollLayout->addWidget(foodEmoji);
auto foodEmoji = new EmojiCategory(tr("Food & Drink"), emoji_provider_.food, scrollWidget);
scrollLayout->addWidget(foodEmoji);
auto activityEmoji = new EmojiCategory(tr("Activity"), emoji_provider_.activity, scrollWidget);
scrollLayout->addWidget(activityEmoji);
auto activityEmoji =
new EmojiCategory(tr("Activity"), emoji_provider_.activity, scrollWidget);
scrollLayout->addWidget(activityEmoji);
auto travelEmoji = new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scrollWidget);
scrollLayout->addWidget(travelEmoji);
auto travelEmoji =
new EmojiCategory(tr("Travel & Places"), emoji_provider_.travel, scrollWidget);
scrollLayout->addWidget(travelEmoji);
auto objectsEmoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scrollWidget);
scrollLayout->addWidget(objectsEmoji);
auto objectsEmoji = new EmojiCategory(tr("Objects"), emoji_provider_.objects, scrollWidget);
scrollLayout->addWidget(objectsEmoji);
auto symbolsEmoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scrollWidget);
scrollLayout->addWidget(symbolsEmoji);
auto symbolsEmoji = new EmojiCategory(tr("Symbols"), emoji_provider_.symbols, scrollWidget);
scrollLayout->addWidget(symbolsEmoji);
auto flagsEmoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scrollWidget);
scrollLayout->addWidget(flagsEmoji);
auto flagsEmoji = new EmojiCategory(tr("Flags"), emoji_provider_.flags, scrollWidget);
scrollLayout->addWidget(flagsEmoji);
contentLayout->addStretch(1);
contentLayout->addWidget(scrollArea_);
contentLayout->addWidget(emojiCategories);
contentLayout->addStretch(1);
contentLayout->addWidget(scrollArea_);
contentLayout->addWidget(emojiCategories);
opacity_ = new QGraphicsOpacityEffect(this);
opacity_->setOpacity(1.0);
opacity_ = new QGraphicsOpacityEffect(this);
opacity_->setOpacity(1.0);
setGraphicsEffect(opacity_);
setGraphicsEffect(opacity_);
animation_ = new QPropertyAnimation(opacity_, "opacity", this);
animation_->setDuration(animationDuration_);
animation_->setStartValue(1);
animation_->setEndValue(0);
animation_ = new QPropertyAnimation(opacity_, "opacity", this);
animation_->setDuration(animationDuration_);
animation_->setStartValue(1);
animation_->setEndValue(0);
connect(peopleEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(peopleCategory, &QPushButton::clicked, [this, peopleEmoji]() { this->showEmojiCategory(peopleEmoji); });
connect(peopleEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(peopleCategory, &QPushButton::clicked, [this, peopleEmoji]() {
this->showEmojiCategory(peopleEmoji);
});
connect(natureEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(natureCategory_, &QPushButton::clicked, [this, natureEmoji]() {
this->showEmojiCategory(natureEmoji);
});
connect(natureEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(natureCategory_, &QPushButton::clicked, [this, natureEmoji]() {
this->showEmojiCategory(natureEmoji);
});
connect(foodEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(foodCategory_, &QPushButton::clicked, [this, foodEmoji]() { this->showEmojiCategory(foodEmoji); });
connect(foodEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(foodCategory_, &QPushButton::clicked, [this, foodEmoji]() {
this->showEmojiCategory(foodEmoji);
});
connect(activityEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(activityCategory, &QPushButton::clicked, [this, activityEmoji]() {
this->showEmojiCategory(activityEmoji);
});
connect(activityEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(activityCategory, &QPushButton::clicked, [this, activityEmoji]() {
this->showEmojiCategory(activityEmoji);
});
connect(travelEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(travelCategory, &QPushButton::clicked, [this, travelEmoji]() { this->showEmojiCategory(travelEmoji); });
connect(travelEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(travelCategory, &QPushButton::clicked, [this, travelEmoji]() {
this->showEmojiCategory(travelEmoji);
});
connect(objectsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(objectsCategory, &QPushButton::clicked, [this, objectsEmoji]() {
this->showEmojiCategory(objectsEmoji);
});
connect(objectsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(objectsCategory, &QPushButton::clicked, [this, objectsEmoji]() {
this->showEmojiCategory(objectsEmoji);
});
connect(symbolsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(symbolsCategory, &QPushButton::clicked, [this, symbolsEmoji]() {
this->showEmojiCategory(symbolsEmoji);
});
connect(symbolsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(symbolsCategory, &QPushButton::clicked, [this, symbolsEmoji]() {
this->showEmojiCategory(symbolsEmoji);
});
connect(flagsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(flagsCategory, &QPushButton::clicked, [this, flagsEmoji]() { this->showEmojiCategory(flagsEmoji); });
connect(flagsEmoji, &EmojiCategory::emojiSelected, this, &EmojiPanel::emojiSelected);
connect(flagsCategory, &QPushButton::clicked, [this, flagsEmoji]() {
this->showEmojiCategory(flagsEmoji);
});
connect(animation_, &QAbstractAnimation::finished, [this]() {
if (animation_->direction() == QAbstractAnimation::Forward)
this->hide();
});
connect(animation_, &QAbstractAnimation::finished, [this]() {
if (animation_->direction() == QAbstractAnimation::Forward)
this->hide();
});
}
void
EmojiPanel::showEmojiCategory(const EmojiCategory *category)
{
auto posToGo = category->mapToParent(QPoint()).y();
auto current = scrollArea_->verticalScrollBar()->value();
auto posToGo = category->mapToParent(QPoint()).y();
auto current = scrollArea_->verticalScrollBar()->value();
if (current == posToGo)
return;
if (current == posToGo)
return;
// HACK
// If we want to go to a previous category and position the label at the top
// the 6*50 offset won't work because not all the categories have the same height.
// To ensure the category is at the top, we move to the top
// and go as normal to the next category.
if (current > posToGo)
this->scrollArea_->ensureVisible(0, 0, 0, 0);
// HACK
// If we want to go to a previous category and position the label at the top
// the 6*50 offset won't work because not all the categories have the same height.
// To ensure the category is at the top, we move to the top
// and go as normal to the next category.
if (current > posToGo)
this->scrollArea_->ensureVisible(0, 0, 0, 0);
posToGo += 6 * 50;
this->scrollArea_->ensureVisible(0, posToGo, 0, 0);
posToGo += 6 * 50;
this->scrollArea_->ensureVisible(0, posToGo, 0, 0);
}
void
EmojiPanel::leaveEvent(QEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(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());
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);
QWidget::paintEvent(event);
}
void
EmojiPanel::fadeOut()
{
animation_->setDirection(QAbstractAnimation::Forward);
animation_->start();
animation_->setDirection(QAbstractAnimation::Forward);
animation_->start();
}
void
EmojiPanel::fadeIn()
{
animation_->setDirection(QAbstractAnimation::Backward);
animation_->start();
animation_->setDirection(QAbstractAnimation::Backward);
animation_->start();
}

View file

@ -28,40 +28,40 @@ EmojiPickButton::EmojiPickButton(QWidget *parent)
void
EmojiPickButton::enterEvent(QEvent *e)
{
Q_UNUSED(e);
Q_UNUSED(e);
if (panel_ == nullptr) {
panel_ = new EmojiPanel(this);
connect(panel_, &EmojiPanel::emojiSelected, this, &EmojiPickButton::emojiSelected);
}
if (panel_ == nullptr) {
panel_ = new EmojiPanel(this);
connect(panel_, &EmojiPanel::emojiSelected, this, &EmojiPickButton::emojiSelected);
}
QPoint pos(rect().x(), rect().y());
pos = this->mapToGlobal(pos);
QPoint pos(rect().x(), rect().y());
pos = this->mapToGlobal(pos);
auto panel_size = panel_->sizeHint();
auto panel_size = panel_->sizeHint();
auto x = pos.x() - panel_size.width() + horizontal_distance_;
auto y = pos.y() - panel_size.height() - vertical_distance_;
auto x = pos.x() - panel_size.width() + horizontal_distance_;
auto y = pos.y() - panel_size.height() - vertical_distance_;
panel_->move(x, y);
panel_->fadeIn();
panel_->show();
panel_->move(x, y);
panel_->fadeIn();
panel_->show();
}
void
EmojiPickButton::leaveEvent(QEvent *e)
{
Q_UNUSED(e);
Q_UNUSED(e);
if (panel_->underMouse())
return;
if (panel_->underMouse())
return;
auto pos = QCursor::pos();
auto panel_geometry = panel_->geometry();
panel_geometry.adjust(0, 0, 0, vertical_distance_);
auto pos = QCursor::pos();
auto panel_geometry = panel_->geometry();
panel_geometry.adjust(0, 0, 0, vertical_distance_);
if (panel_geometry.contains(pos))
return;
if (panel_geometry.contains(pos))
return;
panel_->fadeOut();
panel_->fadeOut();
}

File diff suppressed because it is too large Load diff

View file

@ -26,169 +26,171 @@
#include "ImageOverlayDialog.h"
namespace events = matrix::events;
namespace msgs = matrix::events::messages;
namespace msgs = matrix::events::messages;
ImageItem::ImageItem(QSharedPointer<MatrixClient> client,
const events::MessageEvent<msgs::Image> &event,
QWidget *parent)
const events::MessageEvent<msgs::Image> &event,
QWidget *parent)
: QWidget(parent)
, event_{ event }
, client_{ client }
{
setMouseTracking(true);
setCursor(Qt::PointingHandCursor);
setAttribute(Qt::WA_Hover, true);
setMouseTracking(true);
setCursor(Qt::PointingHandCursor);
setAttribute(Qt::WA_Hover, true);
url_ = event.msgContent().url();
text_ = event.content().body();
url_ = event.msgContent().url();
text_ = event.content().body();
QList<QString> url_parts = url_.toString().split("mxc://");
QList<QString> url_parts = url_.toString().split("mxc://");
if (url_parts.size() != 2) {
qDebug() << "Invalid format for image" << url_.toString();
return;
}
if (url_parts.size() != 2) {
qDebug() << "Invalid format for image" << url_.toString();
return;
}
QString media_params = url_parts[1];
url_ = QString("%1/_matrix/media/r0/download/%2").arg(client_.data()->getHomeServer().toString(), media_params);
QString media_params = url_parts[1];
url_ = QString("%1/_matrix/media/r0/download/%2")
.arg(client_.data()->getHomeServer().toString(), media_params);
client_.data()->downloadImage(event.eventId(), url_);
client_.data()->downloadImage(event.eventId(), url_);
connect(client_.data(),
SIGNAL(imageDownloaded(const QString &, const QPixmap &)),
this,
SLOT(imageDownloaded(const QString &, const QPixmap &)));
connect(client_.data(),
SIGNAL(imageDownloaded(const QString &, const QPixmap &)),
this,
SLOT(imageDownloaded(const QString &, const QPixmap &)));
}
void
ImageItem::imageDownloaded(const QString &event_id, const QPixmap &img)
{
if (event_id != event_.eventId())
return;
if (event_id != event_.eventId())
return;
setImage(img);
setImage(img);
}
void
ImageItem::openUrl()
{
if (url_.toString().isEmpty())
return;
if (url_.toString().isEmpty())
return;
if (!QDesktopServices::openUrl(url_))
qWarning() << "Could not open url" << url_.toString();
if (!QDesktopServices::openUrl(url_))
qWarning() << "Could not open url" << url_.toString();
}
void
ImageItem::scaleImage()
{
if (image_.isNull())
return;
if (image_.isNull())
return;
auto width_ratio = (double)max_width_ / (double)image_.width();
auto height_ratio = (double)max_height_ / (double)image_.height();
auto width_ratio = (double)max_width_ / (double)image_.width();
auto height_ratio = (double)max_height_ / (double)image_.height();
auto min_aspect_ratio = std::min(width_ratio, height_ratio);
auto min_aspect_ratio = std::min(width_ratio, height_ratio);
if (min_aspect_ratio > 1) {
width_ = image_.width();
height_ = image_.height();
} else {
width_ = image_.width() * min_aspect_ratio;
height_ = image_.height() * min_aspect_ratio;
}
if (min_aspect_ratio > 1) {
width_ = image_.width();
height_ = image_.height();
} else {
width_ = image_.width() * min_aspect_ratio;
height_ = image_.height() * min_aspect_ratio;
}
setFixedSize(width_, height_);
scaled_image_ = image_.scaled(width_, height_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
setFixedSize(width_, height_);
scaled_image_ =
image_.scaled(width_, height_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
QSize
ImageItem::sizeHint() const
{
if (image_.isNull())
return QSize(max_width_, bottom_height_);
if (image_.isNull())
return QSize(max_width_, bottom_height_);
return QSize(width_, height_);
return QSize(width_, height_);
}
void
ImageItem::setImage(const QPixmap &image)
{
image_ = image;
scaleImage();
update();
image_ = image;
scaleImage();
update();
}
void
ImageItem::mousePressEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton)
return;
if (event->button() != Qt::LeftButton)
return;
if (image_.isNull()) {
openUrl();
return;
}
if (image_.isNull()) {
openUrl();
return;
}
auto point = event->pos();
auto point = event->pos();
// Click on the text box.
if (QRect(0, height_ - bottom_height_, width_, bottom_height_).contains(point)) {
openUrl();
} else {
auto image_dialog = new ImageOverlayDialog(image_, this);
image_dialog->show();
}
// Click on the text box.
if (QRect(0, height_ - bottom_height_, width_, bottom_height_).contains(point)) {
openUrl();
} else {
auto image_dialog = new ImageOverlayDialog(image_, this);
image_dialog->show();
}
}
void
ImageItem::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event);
scaleImage();
scaleImage();
}
void
ImageItem::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QFont font("Open Sans");
font.setPixelSize(12);
QFont font("Open Sans");
font.setPixelSize(12);
QFontMetrics metrics(font);
int fontHeight = metrics.height();
QFontMetrics metrics(font);
int fontHeight = metrics.height();
if (image_.isNull()) {
int height = fontHeight + 10;
if (image_.isNull()) {
int height = fontHeight + 10;
QString elidedText = metrics.elidedText(text_, Qt::ElideRight, max_width_ - 10);
QString elidedText = metrics.elidedText(text_, Qt::ElideRight, max_width_ - 10);
setFixedSize(metrics.width(elidedText), fontHeight + 10);
setFixedSize(metrics.width(elidedText), fontHeight + 10);
painter.setFont(font);
painter.setPen(QPen(QColor(66, 133, 244)));
painter.drawText(QPoint(0, height / 2 + 2), elidedText);
painter.setFont(font);
painter.setPen(QPen(QColor(66, 133, 244)));
painter.drawText(QPoint(0, height / 2 + 2), elidedText);
return;
}
return;
}
painter.fillRect(QRect(0, 0, width_, height_), scaled_image_);
painter.fillRect(QRect(0, 0, width_, height_), scaled_image_);
if (underMouse()) {
// Bottom text section
painter.fillRect(QRect(0, height_ - bottom_height_, width_, bottom_height_),
QBrush(QColor(33, 33, 33, 128)));
if (underMouse()) {
// Bottom text section
painter.fillRect(QRect(0, height_ - bottom_height_, width_, bottom_height_),
QBrush(QColor(33, 33, 33, 128)));
QString elidedText = metrics.elidedText(text_, Qt::ElideRight, width_ - 10);
QString elidedText = metrics.elidedText(text_, Qt::ElideRight, width_ - 10);
font.setWeight(500);
painter.setFont(font);
painter.setPen(QPen(QColor("white")));
painter.drawText(QPoint(5, height_ - fontHeight / 2), elidedText);
}
font.setWeight(500);
painter.setFont(font);
painter.setPen(QPen(QColor("white")));
painter.drawText(QPoint(5, height_ - fontHeight / 2), elidedText);
}
}

View file

@ -28,103 +28,105 @@ ImageOverlayDialog::ImageOverlayDialog(QPixmap image, QWidget *parent)
: QWidget{ parent }
, originalImage_{ image }
{
setMouseTracking(true);
setParent(0);
setMouseTracking(true);
setParent(0);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_DeleteOnClose, true);
setWindowState(Qt::WindowFullScreen);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_DeleteOnClose, true);
setWindowState(Qt::WindowFullScreen);
screen_ = QApplication::desktop()->availableGeometry();
screen_ = QApplication::desktop()->availableGeometry();
move(QApplication::desktop()->mapToGlobal(screen_.topLeft()));
resize(screen_.size());
move(QApplication::desktop()->mapToGlobal(screen_.topLeft()));
resize(screen_.size());
connect(this, SIGNAL(closing()), this, SLOT(close()));
connect(this, SIGNAL(closing()), this, SLOT(close()));
raise();
raise();
}
// TODO: Move this into Utils
void
ImageOverlayDialog::scaleImage(int max_width, int max_height)
{
if (originalImage_.isNull())
return;
if (originalImage_.isNull())
return;
auto width_ratio = (double)max_width / (double)originalImage_.width();
auto height_ratio = (double)max_height / (double)originalImage_.height();
auto width_ratio = (double)max_width / (double)originalImage_.width();
auto height_ratio = (double)max_height / (double)originalImage_.height();
auto min_aspect_ratio = std::min(width_ratio, height_ratio);
auto min_aspect_ratio = std::min(width_ratio, height_ratio);
int final_width = 0;
int final_height = 0;
int final_width = 0;
int final_height = 0;
if (min_aspect_ratio > 1) {
final_width = originalImage_.width();
final_height = originalImage_.height();
} else {
final_width = originalImage_.width() * min_aspect_ratio;
final_height = originalImage_.height() * min_aspect_ratio;
}
if (min_aspect_ratio > 1) {
final_width = originalImage_.width();
final_height = originalImage_.height();
} else {
final_width = originalImage_.width() * min_aspect_ratio;
final_height = originalImage_.height() * min_aspect_ratio;
}
image_ = originalImage_.scaled(final_width, final_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
image_ = originalImage_.scaled(
final_width, final_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
void
ImageOverlayDialog::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Full screen overlay.
painter.fillRect(QRect(0, 0, screen_.width(), screen_.height()), QColor(55, 55, 55, 170));
// Full screen overlay.
painter.fillRect(QRect(0, 0, screen_.width(), screen_.height()), QColor(55, 55, 55, 170));
// Left and Right margins
int outer_margin = screen_.width() * 0.12;
int buttonSize = 36;
int margin = outer_margin * 0.1;
// Left and Right margins
int outer_margin = screen_.width() * 0.12;
int buttonSize = 36;
int margin = outer_margin * 0.1;
int max_width = screen_.width() - 2 * outer_margin;
int max_height = screen_.height();
int max_width = screen_.width() - 2 * outer_margin;
int max_height = screen_.height();
scaleImage(max_width, max_height);
scaleImage(max_width, max_height);
int diff_x = max_width - image_.width();
int diff_y = max_height - image_.height();
int diff_x = max_width - image_.width();
int diff_y = max_height - image_.height();
content_ = QRect(outer_margin + diff_x / 2, diff_y / 2, image_.width(), image_.height());
close_button_ = QRect(screen_.width() - margin - buttonSize, margin, buttonSize, buttonSize);
content_ = QRect(outer_margin + diff_x / 2, diff_y / 2, image_.width(), image_.height());
close_button_ =
QRect(screen_.width() - margin - buttonSize, margin, buttonSize, buttonSize);
// Draw main content_.
painter.drawPixmap(content_, image_);
// Draw main content_.
painter.drawPixmap(content_, image_);
// Draw top right corner X.
QPen pen;
pen.setCapStyle(Qt::RoundCap);
pen.setWidthF(5);
pen.setColor("gray");
// Draw top right corner X.
QPen pen;
pen.setCapStyle(Qt::RoundCap);
pen.setWidthF(5);
pen.setColor("gray");
auto center = close_button_.center();
auto center = close_button_.center();
painter.setPen(pen);
painter.drawLine(center - QPointF(15, 15), center + QPointF(15, 15));
painter.drawLine(center + QPointF(15, -15), center - QPointF(15, -15));
painter.setPen(pen);
painter.drawLine(center - QPointF(15, 15), center + QPointF(15, 15));
painter.drawLine(center + QPointF(15, -15), center - QPointF(15, -15));
}
void
ImageOverlayDialog::mousePressEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton)
return;
if (event->button() != Qt::LeftButton)
return;
if (close_button_.contains(event->pos()))
emit closing();
else if (!content_.contains(event->pos()))
emit closing();
if (close_button_.contains(event->pos()))
emit closing();
else if (!content_.contains(event->pos()))
emit closing();
}

View file

@ -20,7 +20,8 @@
const QRegExp MXID_REGEX("@[A-Za-z0-9._%+-]+:[A-Za-z0-9.-]{1,126}\\.[A-Za-z]{1,63}");
const QRegExp LOCALPART_REGEX("[A-za-z0-9._%+-]{3,}");
const QRegExp PASSWORD_REGEX(".{8,}");
const QRegExp DOMAIN_REGEX("(?!\\-)(?:[a-zA-Z\\d\\-]{0,62}[a-zA-Z\\d]\\.){1,126}(?!\\d+)[a-zA-Z\\d]{1,63}");
const QRegExp DOMAIN_REGEX(
"(?!\\-)(?:[a-zA-Z\\d\\-]{0,62}[a-zA-Z\\d]\\.){1,126}(?!\\d+)[a-zA-Z\\d]{1,63}");
QRegExpValidator InputValidator::Id(MXID_REGEX);
QRegExpValidator InputValidator::Localpart(LOCALPART_REGEX);

View file

@ -36,43 +36,43 @@ QByteArray
LoginRequest::serialize() noexcept
{
#if defined(Q_OS_MAC)
QString initialDeviceName("nheko on Mac OS");
QString initialDeviceName("nheko on Mac OS");
#elif defined(Q_OS_LINUX)
QString initialDeviceName("nheko on Linux");
QString initialDeviceName("nheko on Linux");
#elif defined(Q_OS_WIN)
QString initialDeviceName("nheko on Windows");
QString initialDeviceName("nheko on Windows");
#else
QString initialDeviceName("nheko");
QString initialDeviceName("nheko");
#endif
QJsonObject body{
{ "type", "m.login.password" },
{ "user", user_ },
{ "password", password_ },
{ "initial_device_display_name", initialDeviceName },
};
QJsonObject body{
{ "type", "m.login.password" },
{ "user", user_ },
{ "password", password_ },
{ "initial_device_display_name", initialDeviceName },
};
return QJsonDocument(body).toJson(QJsonDocument::Compact);
return QJsonDocument(body).toJson(QJsonDocument::Compact);
}
void
LoginResponse::deserialize(const QJsonDocument &data)
{
if (!data.isObject())
throw DeserializationException("Login response is not a JSON object");
if (!data.isObject())
throw DeserializationException("Login response is not a JSON object");
QJsonObject object = data.object();
QJsonObject object = data.object();
if (object.value("access_token") == QJsonValue::Undefined)
throw DeserializationException("Login: missing access_token param");
if (object.value("access_token") == QJsonValue::Undefined)
throw DeserializationException("Login: missing access_token param");
if (object.value("home_server") == QJsonValue::Undefined)
throw DeserializationException("Login: missing home_server param");
if (object.value("home_server") == QJsonValue::Undefined)
throw DeserializationException("Login: missing home_server param");
if (object.value("user_id") == QJsonValue::Undefined)
throw DeserializationException("Login: missing user_id param");
if (object.value("user_id") == QJsonValue::Undefined)
throw DeserializationException("Login: missing user_id param");
access_token_ = object.value("access_token").toString();
home_server_ = object.value("home_server").toString();
user_id_ = object.value("user_id").toString();
access_token_ = object.value("access_token").toString();
home_server_ = object.value("home_server").toString();
user_id_ = object.value("user_id").toString();
}

View file

@ -26,274 +26,275 @@ LoginPage::LoginPage(QSharedPointer<MatrixClient> client, QWidget *parent)
, inferredServerAddress_()
, client_{ client }
{
setStyleSheet("background-color: #f9f9f9");
setStyleSheet("background-color: #f9f9f9");
top_layout_ = new QVBoxLayout();
top_layout_ = new QVBoxLayout();
top_bar_layout_ = new QHBoxLayout();
top_bar_layout_->setSpacing(0);
top_bar_layout_->setMargin(0);
top_bar_layout_ = new QHBoxLayout();
top_bar_layout_->setSpacing(0);
top_bar_layout_->setMargin(0);
back_button_ = new FlatButton(this);
back_button_->setMinimumSize(QSize(30, 30));
back_button_->setForegroundColor("#333333");
back_button_ = new FlatButton(this);
back_button_->setMinimumSize(QSize(30, 30));
back_button_->setForegroundColor("#333333");
top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
top_bar_layout_->addStretch(1);
top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
top_bar_layout_->addStretch(1);
QIcon icon;
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
QIcon icon;
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
back_button_->setIcon(icon);
back_button_->setIconSize(QSize(24, 24));
back_button_->setIcon(icon);
back_button_->setIconSize(QSize(24, 24));
QIcon advanced_settings_icon;
advanced_settings_icon.addFile(":/icons/icons/cog.png", QSize(), QIcon::Normal, QIcon::Off);
QIcon advanced_settings_icon;
advanced_settings_icon.addFile(":/icons/icons/cog.png", QSize(), QIcon::Normal, QIcon::Off);
logo_ = new QLabel(this);
logo_->setPixmap(QPixmap(":/logos/nheko-128.png"));
logo_ = new QLabel(this);
logo_->setPixmap(QPixmap(":/logos/nheko-128.png"));
logo_layout_ = new QHBoxLayout();
logo_layout_->setContentsMargins(0, 0, 0, 20);
logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
logo_layout_ = new QHBoxLayout();
logo_layout_->setContentsMargins(0, 0, 0, 20);
logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
form_wrapper_ = new QHBoxLayout();
form_widget_ = new QWidget();
form_widget_->setMinimumSize(QSize(350, 200));
form_wrapper_ = new QHBoxLayout();
form_widget_ = new QWidget();
form_widget_->setMinimumSize(QSize(350, 200));
form_layout_ = new QVBoxLayout();
form_layout_->setSpacing(20);
form_layout_->setContentsMargins(0, 0, 0, 30);
form_widget_->setLayout(form_layout_);
form_layout_ = new QVBoxLayout();
form_layout_->setSpacing(20);
form_layout_->setContentsMargins(0, 0, 0, 30);
form_widget_->setLayout(form_layout_);
form_wrapper_->addStretch(1);
form_wrapper_->addWidget(form_widget_);
form_wrapper_->addStretch(1);
form_wrapper_->addStretch(1);
form_wrapper_->addWidget(form_widget_);
form_wrapper_->addStretch(1);
matrixid_input_ = new TextField(this);
matrixid_input_->setTextColor("#333333");
matrixid_input_->setLabel(tr("Matrix ID"));
matrixid_input_->setInkColor("#555459");
matrixid_input_->setBackgroundColor("#f9f9f9");
matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
matrixid_input_ = new TextField(this);
matrixid_input_->setTextColor("#333333");
matrixid_input_->setLabel(tr("Matrix ID"));
matrixid_input_->setInkColor("#555459");
matrixid_input_->setBackgroundColor("#f9f9f9");
matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
spinner_ = new CircularProgress(this);
spinner_->setColor("#acc7dc");
spinner_->setSize(32);
spinner_->setMaximumWidth(spinner_->width());
spinner_->hide();
spinner_ = new CircularProgress(this);
spinner_->setColor("#acc7dc");
spinner_->setSize(32);
spinner_->setMaximumWidth(spinner_->width());
spinner_->hide();
errorIcon_ = new QLabel(this);
errorIcon_->setPixmap(QPixmap(":/icons/icons/error.png"));
errorIcon_->hide();
errorIcon_ = new QLabel(this);
errorIcon_->setPixmap(QPixmap(":/icons/icons/error.png"));
errorIcon_->hide();
matrixidLayout_ = new QHBoxLayout();
matrixidLayout_->addWidget(matrixid_input_, 0, Qt::AlignVCenter);
matrixidLayout_ = new QHBoxLayout();
matrixidLayout_->addWidget(matrixid_input_, 0, Qt::AlignVCenter);
password_input_ = new TextField(this);
password_input_->setTextColor("#333333");
password_input_->setLabel(tr("Password"));
password_input_->setInkColor("#555459");
password_input_->setBackgroundColor("#f9f9f9");
password_input_->setEchoMode(QLineEdit::Password);
password_input_ = new TextField(this);
password_input_->setTextColor("#333333");
password_input_->setLabel(tr("Password"));
password_input_->setInkColor("#555459");
password_input_->setBackgroundColor("#f9f9f9");
password_input_->setEchoMode(QLineEdit::Password);
serverInput_ = new TextField(this);
serverInput_->setTextColor("#333333");
serverInput_->setLabel("Homeserver address");
serverInput_->setInkColor("#555459");
serverInput_->setBackgroundColor("#f9f9f9");
serverInput_->setPlaceholderText("matrix.org");
serverInput_->hide();
serverInput_ = new TextField(this);
serverInput_->setTextColor("#333333");
serverInput_->setLabel("Homeserver address");
serverInput_->setInkColor("#555459");
serverInput_->setBackgroundColor("#f9f9f9");
serverInput_->setPlaceholderText("matrix.org");
serverInput_->hide();
serverLayout_ = new QHBoxLayout();
serverLayout_->addWidget(serverInput_, 0, Qt::AlignVCenter);
serverLayout_ = new QHBoxLayout();
serverLayout_->addWidget(serverInput_, 0, Qt::AlignVCenter);
form_layout_->addLayout(matrixidLayout_);
form_layout_->addWidget(password_input_, Qt::AlignHCenter, 0);
form_layout_->addLayout(serverLayout_);
form_layout_->addLayout(matrixidLayout_);
form_layout_->addWidget(password_input_, Qt::AlignHCenter, 0);
form_layout_->addLayout(serverLayout_);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
button_layout_->setContentsMargins(0, 0, 0, 30);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
button_layout_->setContentsMargins(0, 0, 0, 30);
login_button_ = new RaisedButton(tr("LOGIN"), this);
login_button_->setBackgroundColor(QColor("#333333"));
login_button_->setForegroundColor(QColor("white"));
login_button_->setMinimumSize(350, 65);
login_button_->setFontSize(20);
login_button_->setCornerRadius(3);
login_button_ = new RaisedButton(tr("LOGIN"), this);
login_button_->setBackgroundColor(QColor("#333333"));
login_button_->setForegroundColor(QColor("white"));
login_button_->setMinimumSize(350, 65);
login_button_->setFontSize(20);
login_button_->setCornerRadius(3);
button_layout_->addStretch(1);
button_layout_->addWidget(login_button_);
button_layout_->addStretch(1);
button_layout_->addStretch(1);
button_layout_->addWidget(login_button_);
button_layout_->addStretch(1);
QFont font;
font.setPixelSize(conf::fontSize);
QFont font;
font.setPixelSize(conf::fontSize);
error_label_ = new QLabel(this);
error_label_->setFont(font);
error_label_->setStyleSheet("color: #E22826");
error_label_ = new QLabel(this);
error_label_->setFont(font);
error_label_->setStyleSheet("color: #E22826");
top_layout_->addLayout(top_bar_layout_);
top_layout_->addStretch(1);
top_layout_->addLayout(logo_layout_);
top_layout_->addLayout(form_wrapper_);
top_layout_->addStretch(1);
top_layout_->addLayout(button_layout_);
top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
top_layout_->addStretch(1);
top_layout_->addLayout(top_bar_layout_);
top_layout_->addStretch(1);
top_layout_->addLayout(logo_layout_);
top_layout_->addLayout(form_wrapper_);
top_layout_->addStretch(1);
top_layout_->addLayout(button_layout_);
top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
top_layout_->addStretch(1);
setLayout(top_layout_);
setLayout(top_layout_);
connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
connect(password_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
connect(serverInput_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
connect(client_.data(), SIGNAL(loginError(QString)), this, SLOT(loginError(QString)));
connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
connect(client_.data(), SIGNAL(versionError(QString)), this, SLOT(versionError(QString)));
connect(client_.data(), SIGNAL(versionSuccess()), this, SLOT(versionSuccess()));
connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered()));
connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
connect(password_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
connect(serverInput_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
connect(client_.data(), SIGNAL(loginError(QString)), this, SLOT(loginError(QString)));
connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
connect(client_.data(), SIGNAL(versionError(QString)), this, SLOT(versionError(QString)));
connect(client_.data(), SIGNAL(versionSuccess()), this, SLOT(versionSuccess()));
connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered()));
}
void
LoginPage::loginError(QString error)
{
error_label_->setText(error);
error_label_->setText(error);
}
bool
LoginPage::isMatrixIdValid()
{
int pos = 0;
auto matrix_id = matrixid_input_->text();
int pos = 0;
auto matrix_id = matrixid_input_->text();
return InputValidator::Id.validate(matrix_id, pos) == QValidator::Acceptable;
return InputValidator::Id.validate(matrix_id, pos) == QValidator::Acceptable;
}
void
LoginPage::onMatrixIdEntered()
{
error_label_->setText("");
error_label_->setText("");
if (!isMatrixIdValid()) {
loginError("You have entered an invalid Matrix ID e.g @joe:matrix.org");
return;
} else if (password_input_->text().isEmpty()) {
loginError(tr("Empty password"));
}
if (!isMatrixIdValid()) {
loginError("You have entered an invalid Matrix ID e.g @joe:matrix.org");
return;
} else if (password_input_->text().isEmpty()) {
loginError(tr("Empty password"));
}
QString homeServer = matrixid_input_->text().split(":").at(1);
if (homeServer != inferredServerAddress_) {
serverInput_->hide();
serverLayout_->removeWidget(errorIcon_);
errorIcon_->hide();
if (serverInput_->isVisible()) {
matrixidLayout_->removeWidget(spinner_);
serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
spinner_->show();
} else {
serverLayout_->removeWidget(spinner_);
matrixidLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
spinner_->show();
}
QString homeServer = matrixid_input_->text().split(":").at(1);
if (homeServer != inferredServerAddress_) {
serverInput_->hide();
serverLayout_->removeWidget(errorIcon_);
errorIcon_->hide();
if (serverInput_->isVisible()) {
matrixidLayout_->removeWidget(spinner_);
serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
spinner_->show();
} else {
serverLayout_->removeWidget(spinner_);
matrixidLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
spinner_->show();
}
inferredServerAddress_ = homeServer;
serverInput_->setText(homeServer);
client_->setServer(homeServer);
client_->versions();
}
inferredServerAddress_ = homeServer;
serverInput_->setText(homeServer);
client_->setServer(homeServer);
client_->versions();
}
}
void
LoginPage::onServerAddressEntered()
{
error_label_->setText("");
client_->setServer(serverInput_->text());
client_->versions();
error_label_->setText("");
client_->setServer(serverInput_->text());
client_->versions();
serverLayout_->removeWidget(errorIcon_);
errorIcon_->hide();
serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
spinner_->show();
serverLayout_->removeWidget(errorIcon_);
errorIcon_->hide();
serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
spinner_->show();
}
void
LoginPage::versionError(QString error)
{
// Matrix homeservers are often kept on a subdomain called 'matrix'
// so let's try that next, unless the address was set explicitly or the domain part of the username already
// points to this subdomain
QUrl currentServer = client_->getHomeServer();
QString mxidAddress = matrixid_input_->text().split(":").at(1);
if (currentServer.host() == inferredServerAddress_ && !currentServer.host().startsWith("matrix")) {
error_label_->setText("");
currentServer.setHost(QString("matrix.") + currentServer.host());
serverInput_->setText(currentServer.host());
client_->setServer(currentServer.host());
client_->versions();
return;
}
// Matrix homeservers are often kept on a subdomain called 'matrix'
// so let's try that next, unless the address was set explicitly or the domain part of the
// username already points to this subdomain
QUrl currentServer = client_->getHomeServer();
QString mxidAddress = matrixid_input_->text().split(":").at(1);
if (currentServer.host() == inferredServerAddress_ &&
!currentServer.host().startsWith("matrix")) {
error_label_->setText("");
currentServer.setHost(QString("matrix.") + currentServer.host());
serverInput_->setText(currentServer.host());
client_->setServer(currentServer.host());
client_->versions();
return;
}
error_label_->setText(error);
serverInput_->show();
error_label_->setText(error);
serverInput_->show();
spinner_->hide();
serverLayout_->removeWidget(spinner_);
serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight);
errorIcon_->show();
matrixidLayout_->removeWidget(spinner_);
spinner_->hide();
serverLayout_->removeWidget(spinner_);
serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight);
errorIcon_->show();
matrixidLayout_->removeWidget(spinner_);
}
void
LoginPage::versionSuccess()
{
serverLayout_->removeWidget(spinner_);
matrixidLayout_->removeWidget(spinner_);
spinner_->hide();
serverLayout_->removeWidget(spinner_);
matrixidLayout_->removeWidget(spinner_);
spinner_->hide();
if (serverInput_->isVisible())
serverInput_->hide();
if (serverInput_->isVisible())
serverInput_->hide();
}
void
LoginPage::onLoginButtonClicked()
{
error_label_->setText("");
error_label_->setText("");
if (!isMatrixIdValid()) {
loginError("You have entered an invalid Matrix ID e.g @joe:matrix.org");
} else if (password_input_->text().isEmpty()) {
loginError("Empty password");
} else {
QString user = matrixid_input_->text().split(":").at(0).split("@").at(1);
QString password = password_input_->text();
client_->setServer(serverInput_->text());
client_->login(user, password);
}
if (!isMatrixIdValid()) {
loginError("You have entered an invalid Matrix ID e.g @joe:matrix.org");
} else if (password_input_->text().isEmpty()) {
loginError("Empty password");
} else {
QString user = matrixid_input_->text().split(":").at(0).split("@").at(1);
QString password = password_input_->text();
client_->setServer(serverInput_->text());
client_->login(user, password);
}
}
void
LoginPage::reset()
{
matrixid_input_->clear();
password_input_->clear();
serverInput_->clear();
matrixid_input_->clear();
password_input_->clear();
serverInput_->clear();
spinner_->hide();
errorIcon_->hide();
serverLayout_->removeWidget(spinner_);
serverLayout_->removeWidget(errorIcon_);
matrixidLayout_->removeWidget(spinner_);
spinner_->hide();
errorIcon_->hide();
serverLayout_->removeWidget(spinner_);
serverLayout_->removeWidget(errorIcon_);
matrixidLayout_->removeWidget(spinner_);
inferredServerAddress_.clear();
inferredServerAddress_.clear();
}
void
LoginPage::onBackButtonClicked()
{
emit backButtonClicked();
emit backButtonClicked();
}
LoginPage::~LoginPage()

View file

@ -25,37 +25,37 @@
LogoutDialog::LogoutDialog(QWidget *parent)
: QFrame(parent)
{
setMaximumSize(400, 400);
setStyleSheet("background-color: #f9f9f9");
setMaximumSize(400, 400);
setStyleSheet("background-color: #f9f9f9");
auto layout = new QVBoxLayout(this);
layout->setSpacing(30);
layout->setMargin(20);
auto layout = new QVBoxLayout(this);
layout->setSpacing(30);
layout->setMargin(20);
auto buttonLayout = new QHBoxLayout();
buttonLayout->setSpacing(0);
buttonLayout->setMargin(0);
auto buttonLayout = new QHBoxLayout();
buttonLayout->setSpacing(0);
buttonLayout->setMargin(0);
confirmBtn_ = new FlatButton("OK", this);
confirmBtn_->setFontSize(conf::btn::fontSize);
confirmBtn_ = new FlatButton("OK", this);
confirmBtn_->setFontSize(conf::btn::fontSize);
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
cancelBtn_->setFontSize(conf::btn::fontSize);
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
cancelBtn_->setFontSize(conf::btn::fontSize);
buttonLayout->addStretch(1);
buttonLayout->addWidget(confirmBtn_);
buttonLayout->addWidget(cancelBtn_);
buttonLayout->addStretch(1);
buttonLayout->addWidget(confirmBtn_);
buttonLayout->addWidget(cancelBtn_);
QFont font;
font.setPixelSize(conf::headerFontSize);
QFont font;
font.setPixelSize(conf::headerFontSize);
auto label = new QLabel(tr("Logout. Are you sure?"), this);
label->setFont(font);
label->setStyleSheet("color: #333333");
auto label = new QLabel(tr("Logout. Are you sure?"), this);
label->setFont(font);
label->setStyleSheet("color: #333333");
layout->addWidget(label);
layout->addLayout(buttonLayout);
layout->addWidget(label);
layout->addLayout(buttonLayout);
connect(confirmBtn_, &QPushButton::clicked, [=]() { emit closing(true); });
connect(cancelBtn_, &QPushButton::clicked, [=]() { emit closing(false); });
connect(confirmBtn_, &QPushButton::clicked, [=]() { emit closing(true); });
connect(cancelBtn_, &QPushButton::clicked, [=]() { emit closing(false); });
}

View file

@ -30,217 +30,221 @@ MainWindow::MainWindow(QWidget *parent)
, progress_modal_{ nullptr }
, spinner_{ nullptr }
{
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setSizePolicy(sizePolicy);
setWindowTitle("nheko");
setObjectName("MainWindow");
setStyleSheet("QWidget#MainWindow {background-color: #f9f9f9}");
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
setSizePolicy(sizePolicy);
setWindowTitle("nheko");
setObjectName("MainWindow");
setStyleSheet("QWidget#MainWindow {background-color: #f9f9f9}");
restoreWindowSize();
setMinimumSize(QSize(conf::window::minWidth, conf::window::minHeight));
restoreWindowSize();
setMinimumSize(QSize(conf::window::minWidth, conf::window::minHeight));
QFont font("Open Sans");
font.setPixelSize(conf::fontSize);
font.setStyleStrategy(QFont::PreferAntialias);
setFont(font);
QFont font("Open Sans");
font.setPixelSize(conf::fontSize);
font.setStyleStrategy(QFont::PreferAntialias);
setFont(font);
client_ = QSharedPointer<MatrixClient>(new MatrixClient("matrix.org"));
trayIcon_ = new TrayIcon(":/logos/nheko-32.png", this);
client_ = QSharedPointer<MatrixClient>(new MatrixClient("matrix.org"));
trayIcon_ = new TrayIcon(":/logos/nheko-32.png", this);
welcome_page_ = new WelcomePage(this);
login_page_ = new LoginPage(client_, this);
register_page_ = new RegisterPage(client_, this);
chat_page_ = new ChatPage(client_, this);
welcome_page_ = new WelcomePage(this);
login_page_ = new LoginPage(client_, this);
register_page_ = new RegisterPage(client_, this);
chat_page_ = new ChatPage(client_, this);
// Initialize sliding widget manager.
sliding_stack_ = new SlidingStackWidget(this);
sliding_stack_->addWidget(welcome_page_);
sliding_stack_->addWidget(login_page_);
sliding_stack_->addWidget(register_page_);
sliding_stack_->addWidget(chat_page_);
// Initialize sliding widget manager.
sliding_stack_ = new SlidingStackWidget(this);
sliding_stack_->addWidget(welcome_page_);
sliding_stack_->addWidget(login_page_);
sliding_stack_->addWidget(register_page_);
sliding_stack_->addWidget(chat_page_);
setCentralWidget(sliding_stack_);
setCentralWidget(sliding_stack_);
connect(welcome_page_, SIGNAL(userLogin()), this, SLOT(showLoginPage()));
connect(welcome_page_, SIGNAL(userRegister()), this, SLOT(showRegisterPage()));
connect(welcome_page_, SIGNAL(userLogin()), this, SLOT(showLoginPage()));
connect(welcome_page_, SIGNAL(userRegister()), this, SLOT(showRegisterPage()));
connect(login_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
connect(register_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
connect(login_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
connect(register_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
connect(chat_page_, SIGNAL(close()), this, SLOT(showWelcomePage()));
connect(chat_page_, SIGNAL(changeWindowTitle(QString)), this, SLOT(setWindowTitle(QString)));
connect(chat_page_, SIGNAL(unreadMessages(int)), trayIcon_, SLOT(setUnreadCount(int)));
connect(chat_page_, SIGNAL(close()), this, SLOT(showWelcomePage()));
connect(
chat_page_, SIGNAL(changeWindowTitle(QString)), this, SLOT(setWindowTitle(QString)));
connect(chat_page_, SIGNAL(unreadMessages(int)), trayIcon_, SLOT(setUnreadCount(int)));
connect(trayIcon_,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this,
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
connect(trayIcon_,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this,
SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
connect(client_.data(),
SIGNAL(loginSuccess(QString, QString, QString)),
this,
SLOT(showChatPage(QString, QString, QString)));
connect(client_.data(),
SIGNAL(loginSuccess(QString, QString, QString)),
this,
SLOT(showChatPage(QString, QString, QString)));
QSettings settings;
QSettings settings;
if (hasActiveUser()) {
QString token = settings.value("auth/access_token").toString();
QString home_server = settings.value("auth/home_server").toString();
QString user_id = settings.value("auth/user_id").toString();
if (hasActiveUser()) {
QString token = settings.value("auth/access_token").toString();
QString home_server = settings.value("auth/home_server").toString();
QString user_id = settings.value("auth/user_id").toString();
showChatPage(user_id, home_server, token);
}
showChatPage(user_id, home_server, token);
}
}
void
MainWindow::restoreWindowSize()
{
QSettings settings;
int savedWidth = settings.value("window/width").toInt();
int savedheight = settings.value("window/height").toInt();
QSettings settings;
int savedWidth = settings.value("window/width").toInt();
int savedheight = settings.value("window/height").toInt();
if (savedWidth == 0 || savedheight == 0)
resize(conf::window::width, conf::window::height);
else
resize(savedWidth, savedheight);
if (savedWidth == 0 || savedheight == 0)
resize(conf::window::width, conf::window::height);
else
resize(savedWidth, savedheight);
}
void
MainWindow::saveCurrentWindowSize()
{
QSettings settings;
QSize current = size();
QSettings settings;
QSize current = size();
settings.setValue("window/width", current.width());
settings.setValue("window/height", current.height());
settings.setValue("window/width", current.width());
settings.setValue("window/height", current.height());
}
void
MainWindow::removeOverlayProgressBar()
{
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, [=]() {
timer->deleteLater();
connect(timer, &QTimer::timeout, [=]() {
timer->deleteLater();
if (progress_modal_ != nullptr) {
progress_modal_->deleteLater();
progress_modal_->fadeOut();
}
if (progress_modal_ != nullptr) {
progress_modal_->deleteLater();
progress_modal_->fadeOut();
}
if (spinner_ != nullptr)
spinner_->deleteLater();
if (spinner_ != nullptr)
spinner_->deleteLater();
progress_modal_ = nullptr;
spinner_ = nullptr;
});
progress_modal_ = nullptr;
spinner_ = nullptr;
});
timer->start(500);
timer->start(500);
}
void
MainWindow::showChatPage(QString userid, QString homeserver, QString token)
{
QSettings settings;
settings.setValue("auth/access_token", token);
settings.setValue("auth/home_server", homeserver);
settings.setValue("auth/user_id", userid);
QSettings settings;
settings.setValue("auth/access_token", token);
settings.setValue("auth/home_server", homeserver);
settings.setValue("auth/user_id", userid);
int index = sliding_stack_->getWidgetIndex(chat_page_);
int modalOpacityDuration = 300;
int index = sliding_stack_->getWidgetIndex(chat_page_);
int modalOpacityDuration = 300;
// If we go directly from the welcome page don't show an animation.
if (sliding_stack_->currentIndex() == 0) {
sliding_stack_->setCurrentIndex(index);
modalOpacityDuration = 0;
} else {
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::LEFT_TO_RIGHT);
}
// If we go directly from the welcome page don't show an animation.
if (sliding_stack_->currentIndex() == 0) {
sliding_stack_->setCurrentIndex(index);
modalOpacityDuration = 0;
} else {
sliding_stack_->slideInIndex(index,
SlidingStackWidget::AnimationDirection::LEFT_TO_RIGHT);
}
if (spinner_ == nullptr) {
spinner_ = new CircularProgress(this);
spinner_->setColor("#acc7dc");
spinner_->setSize(100);
}
if (spinner_ == nullptr) {
spinner_ = new CircularProgress(this);
spinner_->setColor("#acc7dc");
spinner_->setSize(100);
}
if (progress_modal_ == nullptr) {
progress_modal_ = new OverlayModal(this, spinner_);
progress_modal_->fadeIn();
progress_modal_->setDuration(modalOpacityDuration);
}
if (progress_modal_ == nullptr) {
progress_modal_ = new OverlayModal(this, spinner_);
progress_modal_->fadeIn();
progress_modal_->setDuration(modalOpacityDuration);
}
login_page_->reset();
chat_page_->bootstrap(userid, homeserver, token);
login_page_->reset();
chat_page_->bootstrap(userid, homeserver, token);
instance_ = this;
instance_ = this;
}
void
MainWindow::showWelcomePage()
{
int index = sliding_stack_->getWidgetIndex(welcome_page_);
int index = sliding_stack_->getWidgetIndex(welcome_page_);
if (sliding_stack_->currentIndex() == sliding_stack_->getWidgetIndex(login_page_))
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::RIGHT_TO_LEFT);
else
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::LEFT_TO_RIGHT);
if (sliding_stack_->currentIndex() == sliding_stack_->getWidgetIndex(login_page_))
sliding_stack_->slideInIndex(index,
SlidingStackWidget::AnimationDirection::RIGHT_TO_LEFT);
else
sliding_stack_->slideInIndex(index,
SlidingStackWidget::AnimationDirection::LEFT_TO_RIGHT);
}
void
MainWindow::showLoginPage()
{
int index = sliding_stack_->getWidgetIndex(login_page_);
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::LEFT_TO_RIGHT);
int index = sliding_stack_->getWidgetIndex(login_page_);
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::LEFT_TO_RIGHT);
}
void
MainWindow::showRegisterPage()
{
int index = sliding_stack_->getWidgetIndex(register_page_);
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::RIGHT_TO_LEFT);
int index = sliding_stack_->getWidgetIndex(register_page_);
sliding_stack_->slideInIndex(index, SlidingStackWidget::AnimationDirection::RIGHT_TO_LEFT);
}
void
MainWindow::closeEvent(QCloseEvent *event)
{
if (isVisible()) {
event->ignore();
hide();
}
if (isVisible()) {
event->ignore();
hide();
}
}
void
MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason) {
case QSystemTrayIcon::Trigger:
if (!isVisible()) {
show();
} else {
hide();
}
break;
default:
break;
}
switch (reason) {
case QSystemTrayIcon::Trigger:
if (!isVisible()) {
show();
} else {
hide();
}
break;
default:
break;
}
}
bool
MainWindow::hasActiveUser()
{
QSettings settings;
QSettings settings;
return settings.contains("auth/access_token") && settings.contains("auth/home_server") &&
settings.contains("auth/user_id");
return settings.contains("auth/access_token") && settings.contains("auth/home_server") &&
settings.contains("auth/user_id");
}
MainWindow *
MainWindow::instance()
{
return instance_;
return instance_;
}
MainWindow::~MainWindow()

View file

@ -25,14 +25,14 @@
void
ProfileResponse::deserialize(const QJsonDocument &data)
{
if (!data.isObject())
throw DeserializationException("Response is not a JSON object");
if (!data.isObject())
throw DeserializationException("Response is not a JSON object");
QJsonObject object = data.object();
QJsonObject object = data.object();
if (object.contains("avatar_url"))
avatar_url_ = QUrl(object.value("avatar_url").toString());
if (object.contains("avatar_url"))
avatar_url_ = QUrl(object.value("avatar_url").toString());
if (object.contains("displayname"))
display_name_ = object.value("displayname").toString();
if (object.contains("displayname"))
display_name_ = object.value("displayname").toString();
}

View file

@ -30,126 +30,127 @@ RoomSearchInput::RoomSearchInput(QWidget *parent)
bool
RoomSearchInput::focusNextPrevChild(bool next)
{
Q_UNUSED(next);
Q_UNUSED(next);
return false;
return false;
}
void
RoomSearchInput::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Down) {
emit selectNextCompletion();
event->accept();
return;
} else if (event->key() == Qt::Key_Up) {
emit selectPreviousCompletion();
event->accept();
return;
}
if (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Down) {
emit selectNextCompletion();
event->accept();
return;
} else if (event->key() == Qt::Key_Up) {
emit selectPreviousCompletion();
event->accept();
return;
}
TextField::keyPressEvent(event);
TextField::keyPressEvent(event);
}
void
RoomSearchInput::hideEvent(QHideEvent *event)
{
emit hiding();
TextField::hideEvent(event);
emit hiding();
TextField::hideEvent(event);
}
QuickSwitcher::QuickSwitcher(QWidget *parent)
: QFrame(parent)
{
setMaximumWidth(450);
setStyleSheet("background-color: white");
setMaximumWidth(450);
setStyleSheet("background-color: white");
QFont font;
font.setPixelSize(20);
QFont font;
font.setPixelSize(20);
roomSearch_ = new RoomSearchInput(this);
roomSearch_->setFont(font);
roomSearch_->setPlaceholderText(tr("Find a room..."));
roomSearch_ = new RoomSearchInput(this);
roomSearch_->setFont(font);
roomSearch_->setPlaceholderText(tr("Find a room..."));
completer_ = new QCompleter();
completer_->setCaseSensitivity(Qt::CaseInsensitive);
completer_->setCompletionMode(QCompleter::PopupCompletion);
completer_->setWidget(this);
completer_ = new QCompleter();
completer_->setCaseSensitivity(Qt::CaseInsensitive);
completer_->setCompletionMode(QCompleter::PopupCompletion);
completer_->setWidget(this);
topLayout_ = new QVBoxLayout(this);
topLayout_->addWidget(roomSearch_);
topLayout_ = new QVBoxLayout(this);
topLayout_->addWidget(roomSearch_);
connect(completer_, SIGNAL(highlighted(QString)), roomSearch_, SLOT(setText(QString)));
connect(roomSearch_, &QLineEdit::textEdited, this, [=](const QString &prefix) {
if (prefix.isEmpty()) {
completer_->popup()->hide();
selection_ = -1;
return;
}
connect(completer_, SIGNAL(highlighted(QString)), roomSearch_, SLOT(setText(QString)));
connect(roomSearch_, &QLineEdit::textEdited, this, [=](const QString &prefix) {
if (prefix.isEmpty()) {
completer_->popup()->hide();
selection_ = -1;
return;
}
if (prefix != completer_->completionPrefix()) {
completer_->setCompletionPrefix(prefix);
selection_ = -1;
}
if (prefix != completer_->completionPrefix()) {
completer_->setCompletionPrefix(prefix);
selection_ = -1;
}
completer_->popup()->setWindowFlags(completer_->popup()->windowFlags() | Qt::ToolTip |
Qt::NoDropShadowWindowHint);
completer_->popup()->setAttribute(Qt::WA_ShowWithoutActivating);
completer_->complete();
});
completer_->popup()->setWindowFlags(completer_->popup()->windowFlags() |
Qt::ToolTip | Qt::NoDropShadowWindowHint);
completer_->popup()->setAttribute(Qt::WA_ShowWithoutActivating);
completer_->complete();
});
connect(roomSearch_, &RoomSearchInput::selectNextCompletion, this, [=]() {
selection_ += 1;
connect(roomSearch_, &RoomSearchInput::selectNextCompletion, this, [=]() {
selection_ += 1;
if (!completer_->setCurrentRow(selection_)) {
selection_ = 0;
completer_->setCurrentRow(selection_);
}
if (!completer_->setCurrentRow(selection_)) {
selection_ = 0;
completer_->setCurrentRow(selection_);
}
completer_->popup()->setCurrentIndex(completer_->currentIndex());
});
completer_->popup()->setCurrentIndex(completer_->currentIndex());
});
connect(roomSearch_, &RoomSearchInput::selectPreviousCompletion, this, [=]() {
selection_ -= 1;
connect(roomSearch_, &RoomSearchInput::selectPreviousCompletion, this, [=]() {
selection_ -= 1;
if (!completer_->setCurrentRow(selection_)) {
selection_ = completer_->completionCount() - 1;
completer_->setCurrentRow(selection_);
}
if (!completer_->setCurrentRow(selection_)) {
selection_ = completer_->completionCount() - 1;
completer_->setCurrentRow(selection_);
}
completer_->popup()->setCurrentIndex(completer_->currentIndex());
});
completer_->popup()->setCurrentIndex(completer_->currentIndex());
});
connect(roomSearch_, &RoomSearchInput::hiding, this, [=]() { completer_->popup()->hide(); });
connect(roomSearch_, &QLineEdit::returnPressed, this, [=]() {
emit closing();
emit roomSelected(rooms_[this->roomSearch_->text().trimmed()]);
connect(
roomSearch_, &RoomSearchInput::hiding, this, [=]() { completer_->popup()->hide(); });
connect(roomSearch_, &QLineEdit::returnPressed, this, [=]() {
emit closing();
emit roomSelected(rooms_[this->roomSearch_->text().trimmed()]);
roomSearch_->clear();
});
roomSearch_->clear();
});
}
void
QuickSwitcher::setRoomList(const QMap<QString, QString> &rooms)
{
rooms_ = rooms;
QStringList items = rooms.keys();
rooms_ = rooms;
QStringList items = rooms.keys();
completer_->setModel(new QStringListModel(items));
completer_->setModel(new QStringListModel(items));
}
void
QuickSwitcher::showEvent(QShowEvent *)
{
roomSearch_->setFocus();
roomSearch_->setFocus();
}
void
QuickSwitcher::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape) {
roomSearch_->clear();
event->accept();
emit closing();
}
if (event->key() == Qt::Key_Escape) {
roomSearch_->clear();
event->accept();
emit closing();
}
}

View file

@ -31,29 +31,29 @@ RegisterRequest::RegisterRequest(const QString &username, const QString &passwor
QByteArray
RegisterRequest::serialize() noexcept
{
QJsonObject body{ { "username", user_ }, { "password", password_ } };
QJsonObject body{ { "username", user_ }, { "password", password_ } };
return QJsonDocument(body).toJson(QJsonDocument::Compact);
return QJsonDocument(body).toJson(QJsonDocument::Compact);
}
void
RegisterResponse::deserialize(const QJsonDocument &data)
{
if (!data.isObject())
throw DeserializationException("Response is not a JSON object");
if (!data.isObject())
throw DeserializationException("Response is not a JSON object");
QJsonObject object = data.object();
QJsonObject object = data.object();
if (!object.contains("access_token"))
throw DeserializationException("Missing access_token param");
if (!object.contains("access_token"))
throw DeserializationException("Missing access_token param");
if (!object.contains("home_server"))
throw DeserializationException("Missing home_server param");
if (!object.contains("home_server"))
throw DeserializationException("Missing home_server param");
if (!object.contains("user_id"))
throw DeserializationException("Missing user_id param");
if (!object.contains("user_id"))
throw DeserializationException("Missing user_id param");
access_token_ = object.value("access_token").toString();
home_server_ = object.value("home_server").toString();
user_id_ = object.value("user_id").toString();
access_token_ = object.value("access_token").toString();
home_server_ = object.value("home_server").toString();
user_id_ = object.value("user_id").toString();
}

View file

@ -26,156 +26,159 @@ RegisterPage::RegisterPage(QSharedPointer<MatrixClient> client, QWidget *parent)
: QWidget(parent)
, client_(client)
{
setStyleSheet("background-color: #f9f9f9");
setStyleSheet("background-color: #f9f9f9");
top_layout_ = new QVBoxLayout();
top_layout_ = new QVBoxLayout();
back_layout_ = new QHBoxLayout();
back_layout_->setSpacing(0);
back_layout_->setContentsMargins(5, 5, -1, -1);
back_layout_ = new QHBoxLayout();
back_layout_->setSpacing(0);
back_layout_->setContentsMargins(5, 5, -1, -1);
back_button_ = new FlatButton(this);
back_button_->setMinimumSize(QSize(30, 30));
back_button_ = new FlatButton(this);
back_button_->setMinimumSize(QSize(30, 30));
QIcon icon;
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
QIcon icon;
icon.addFile(":/icons/icons/left-angle.png", QSize(), QIcon::Normal, QIcon::Off);
back_button_->setIcon(icon);
back_button_->setIconSize(QSize(24, 24));
back_button_->setIcon(icon);
back_button_->setIconSize(QSize(24, 24));
back_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
back_layout_->addStretch(1);
back_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
back_layout_->addStretch(1);
logo_ = new Avatar(this);
logo_->setImage(QImage(":/logos/nheko-128.png"));
logo_->setSize(80);
logo_ = new Avatar(this);
logo_->setImage(QImage(":/logos/nheko-128.png"));
logo_->setSize(80);
logo_layout_ = new QHBoxLayout();
logo_layout_->setMargin(0);
logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
logo_layout_ = new QHBoxLayout();
logo_layout_->setMargin(0);
logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
form_wrapper_ = new QHBoxLayout();
form_widget_ = new QWidget();
form_widget_->setMinimumSize(QSize(350, 300));
form_wrapper_ = new QHBoxLayout();
form_widget_ = new QWidget();
form_widget_->setMinimumSize(QSize(350, 300));
form_layout_ = new QVBoxLayout();
form_layout_->setSpacing(20);
form_layout_->setContentsMargins(0, 0, 0, 40);
form_widget_->setLayout(form_layout_);
form_layout_ = new QVBoxLayout();
form_layout_->setSpacing(20);
form_layout_->setContentsMargins(0, 0, 0, 40);
form_widget_->setLayout(form_layout_);
form_wrapper_->addStretch(1);
form_wrapper_->addWidget(form_widget_);
form_wrapper_->addStretch(1);
form_wrapper_->addStretch(1);
form_wrapper_->addWidget(form_widget_);
form_wrapper_->addStretch(1);
username_input_ = new TextField();
username_input_->setTextColor("#333333");
username_input_->setLabel(tr("Username"));
username_input_->setInkColor("#555459");
username_input_->setBackgroundColor("#f9f9f9");
username_input_ = new TextField();
username_input_->setTextColor("#333333");
username_input_->setLabel(tr("Username"));
username_input_->setInkColor("#555459");
username_input_->setBackgroundColor("#f9f9f9");
password_input_ = new TextField();
password_input_->setTextColor("#333333");
password_input_->setLabel(tr("Password"));
password_input_->setInkColor("#555459");
password_input_->setBackgroundColor("#f9f9f9");
password_input_->setEchoMode(QLineEdit::Password);
password_input_ = new TextField();
password_input_->setTextColor("#333333");
password_input_->setLabel(tr("Password"));
password_input_->setInkColor("#555459");
password_input_->setBackgroundColor("#f9f9f9");
password_input_->setEchoMode(QLineEdit::Password);
password_confirmation_ = new TextField();
password_confirmation_->setTextColor("#333333");
password_confirmation_->setLabel(tr("Password confirmation"));
password_confirmation_->setInkColor("#555459");
password_confirmation_->setBackgroundColor("#f9f9f9");
password_confirmation_->setEchoMode(QLineEdit::Password);
password_confirmation_ = new TextField();
password_confirmation_->setTextColor("#333333");
password_confirmation_->setLabel(tr("Password confirmation"));
password_confirmation_->setInkColor("#555459");
password_confirmation_->setBackgroundColor("#f9f9f9");
password_confirmation_->setEchoMode(QLineEdit::Password);
server_input_ = new TextField();
server_input_->setTextColor("#333333");
server_input_->setLabel(tr("Home Server"));
server_input_->setInkColor("#555459");
server_input_->setBackgroundColor("#f9f9f9");
server_input_ = new TextField();
server_input_->setTextColor("#333333");
server_input_->setLabel(tr("Home Server"));
server_input_->setInkColor("#555459");
server_input_->setBackgroundColor("#f9f9f9");
form_layout_->addWidget(username_input_, Qt::AlignHCenter, 0);
form_layout_->addWidget(password_input_, Qt::AlignHCenter, 0);
form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter, 0);
form_layout_->addWidget(server_input_, Qt::AlignHCenter, 0);
form_layout_->addWidget(username_input_, Qt::AlignHCenter, 0);
form_layout_->addWidget(password_input_, Qt::AlignHCenter, 0);
form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter, 0);
form_layout_->addWidget(server_input_, Qt::AlignHCenter, 0);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
button_layout_->setMargin(0);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
button_layout_->setMargin(0);
QFont font;
font.setPixelSize(conf::fontSize);
QFont font;
font.setPixelSize(conf::fontSize);
error_label_ = new QLabel(this);
error_label_->setFont(font);
error_label_->setStyleSheet("color: #E22826");
error_label_ = new QLabel(this);
error_label_->setFont(font);
error_label_->setStyleSheet("color: #E22826");
register_button_ = new RaisedButton(tr("REGISTER"), this);
register_button_->setBackgroundColor(QColor("#333333"));
register_button_->setForegroundColor(QColor("white"));
register_button_->setMinimumSize(350, 65);
register_button_->setFontSize(conf::btn::fontSize);
register_button_->setCornerRadius(conf::btn::cornerRadius);
register_button_ = new RaisedButton(tr("REGISTER"), this);
register_button_->setBackgroundColor(QColor("#333333"));
register_button_->setForegroundColor(QColor("white"));
register_button_->setMinimumSize(350, 65);
register_button_->setFontSize(conf::btn::fontSize);
register_button_->setCornerRadius(conf::btn::cornerRadius);
button_layout_->addStretch(1);
button_layout_->addWidget(register_button_);
button_layout_->addStretch(1);
button_layout_->addStretch(1);
button_layout_->addWidget(register_button_);
button_layout_->addStretch(1);
top_layout_->addLayout(back_layout_);
top_layout_->addLayout(logo_layout_);
top_layout_->addLayout(form_wrapper_);
top_layout_->addStretch(1);
top_layout_->addLayout(button_layout_);
top_layout_->addStretch(1);
top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
top_layout_->addLayout(back_layout_);
top_layout_->addLayout(logo_layout_);
top_layout_->addLayout(form_wrapper_);
top_layout_->addStretch(1);
top_layout_->addLayout(button_layout_);
top_layout_->addStretch(1);
top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
connect(username_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(password_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(password_confirmation_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(server_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(client_.data(), SIGNAL(registerError(const QString &)), this, SLOT(registerError(const QString &)));
connect(username_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(password_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(password_confirmation_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(server_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
connect(client_.data(),
SIGNAL(registerError(const QString &)),
this,
SLOT(registerError(const QString &)));
username_input_->setValidator(&InputValidator::Localpart);
password_input_->setValidator(&InputValidator::Password);
server_input_->setValidator(&InputValidator::Domain);
username_input_->setValidator(&InputValidator::Localpart);
password_input_->setValidator(&InputValidator::Password);
server_input_->setValidator(&InputValidator::Domain);
setLayout(top_layout_);
setLayout(top_layout_);
}
void
RegisterPage::onBackButtonClicked()
{
emit backButtonClicked();
emit backButtonClicked();
}
void
RegisterPage::registerError(const QString &msg)
{
error_label_->setText(msg);
error_label_->setText(msg);
}
void
RegisterPage::onRegisterButtonClicked()
{
error_label_->setText("");
error_label_->setText("");
if (!username_input_->hasAcceptableInput()) {
registerError(tr("Invalid username"));
} else if (!password_input_->hasAcceptableInput()) {
registerError(tr("Password is not long enough (min 8 chars)"));
} else if (password_input_->text() != password_confirmation_->text()) {
registerError(tr("Passwords don't match"));
} else if (!server_input_->hasAcceptableInput()) {
registerError(tr("Invalid server name"));
} else {
QString username = username_input_->text();
QString password = password_input_->text();
QString server = server_input_->text();
if (!username_input_->hasAcceptableInput()) {
registerError(tr("Invalid username"));
} else if (!password_input_->hasAcceptableInput()) {
registerError(tr("Password is not long enough (min 8 chars)"));
} else if (password_input_->text() != password_confirmation_->text()) {
registerError(tr("Passwords don't match"));
} else if (!server_input_->hasAcceptableInput()) {
registerError(tr("Invalid server name"));
} else {
QString username = username_input_->text();
QString password = password_input_->text();
QString server = server_input_->text();
client_->registerUser(username, password, server);
}
client_->registerUser(username, password, server);
}
}
RegisterPage::~RegisterPage()

View file

@ -26,9 +26,9 @@
#include "Theme.h"
RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
RoomState state,
QString room_id,
QWidget *parent)
RoomState state,
QString room_id,
QWidget *parent)
: QWidget(parent)
, state_(state)
, roomId_(room_id)
@ -37,264 +37,277 @@ RoomInfoListItem::RoomInfoListItem(QSharedPointer<RoomSettings> settings,
, maxHeight_(IconSize + 2 * Padding)
, unreadMsgCount_(0)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setMouseTracking(true);
setAttribute(Qt::WA_Hover);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setMouseTracking(true);
setAttribute(Qt::WA_Hover);
setFixedHeight(maxHeight_);
setFixedHeight(maxHeight_);
QPainterPath path;
path.addRect(0, 0, parent->width(), height());
QPainterPath path;
path.addRect(0, 0, parent->width(), height());
ripple_overlay_ = new RippleOverlay(this);
ripple_overlay_->setClipPath(path);
ripple_overlay_->setClipping(true);
ripple_overlay_ = new RippleOverlay(this);
ripple_overlay_->setClipPath(path);
ripple_overlay_->setClipping(true);
menu_ = new Menu(this);
menu_ = new Menu(this);
toggleNotifications_ = new QAction(notificationText(), this);
toggleNotifications_ = new QAction(notificationText(), this);
connect(toggleNotifications_, &QAction::triggered, this, [=]() { roomSettings_->toggleNotifications(); });
connect(toggleNotifications_, &QAction::triggered, this, [=]() {
roomSettings_->toggleNotifications();
});
menu_->addAction(toggleNotifications_);
menu_->addAction(toggleNotifications_);
}
QString
RoomInfoListItem::notificationText()
{
if (roomSettings_.isNull() || roomSettings_->isNotificationsEnabled())
return QString(tr("Disable notifications"));
if (roomSettings_.isNull() || roomSettings_->isNotificationsEnabled())
return QString(tr("Disable notifications"));
return tr("Enable notifications");
return tr("Enable notifications");
}
void
RoomInfoListItem::resizeEvent(QResizeEvent *)
{
// Update ripple's clipping path.
QPainterPath path;
path.addRect(0, 0, width(), height());
// Update ripple's clipping path.
QPainterPath path;
path.addRect(0, 0, width(), height());
ripple_overlay_->setClipPath(path);
ripple_overlay_->setClipping(true);
ripple_overlay_->setClipPath(path);
ripple_overlay_->setClipping(true);
}
void
RoomInfoListItem::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event);
QPainter p(this);
p.setRenderHint(QPainter::TextAntialiasing);
p.setRenderHint(QPainter::SmoothPixmapTransform);
p.setRenderHint(QPainter::Antialiasing);
QPainter p(this);
p.setRenderHint(QPainter::TextAntialiasing);
p.setRenderHint(QPainter::SmoothPixmapTransform);
p.setRenderHint(QPainter::Antialiasing);
if (isPressed_)
p.fillRect(rect(), QColor("#38A3D8"));
else if (underMouse())
p.fillRect(rect(), QColor(200, 200, 200, 128));
else
p.fillRect(rect(), QColor("#F8FBFE"));
if (isPressed_)
p.fillRect(rect(), QColor("#38A3D8"));
else if (underMouse())
p.fillRect(rect(), QColor(200, 200, 200, 128));
else
p.fillRect(rect(), QColor("#F8FBFE"));
QFont font;
font.setPixelSize(conf::fontSize);
QFontMetrics metrics(font);
QFont font;
font.setPixelSize(conf::fontSize);
QFontMetrics metrics(font);
p.setPen(QColor("#333"));
p.setPen(QColor("#333"));
QRect avatarRegion(Padding, Padding, IconSize, IconSize);
QRect avatarRegion(Padding, Padding, IconSize, IconSize);
// Description line with the default font.
int bottom_y = maxHeight_ - Padding - Padding / 3 - metrics.ascent() / 2;
// Description line with the default font.
int bottom_y = maxHeight_ - Padding - Padding / 3 - metrics.ascent() / 2;
if (width() > ui::sidebar::SmallSize) {
if (isPressed_) {
QPen pen(QColor("white"));
p.setPen(pen);
}
if (width() > ui::sidebar::SmallSize) {
if (isPressed_) {
QPen pen(QColor("white"));
p.setPen(pen);
}
font.setPixelSize(conf::roomlist::fonts::heading);
p.setFont(font);
font.setPixelSize(conf::roomlist::fonts::heading);
p.setFont(font);
// Name line.
QFontMetrics fontNameMetrics(font);
int top_y = 2 * Padding + fontNameMetrics.ascent() / 2;
// Name line.
QFontMetrics fontNameMetrics(font);
int top_y = 2 * Padding + fontNameMetrics.ascent() / 2;
auto name =
metrics.elidedText(state_.getName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8);
p.drawText(QPoint(2 * Padding + IconSize, top_y), name);
auto name = metrics.elidedText(
state_.getName(), Qt::ElideRight, (width() - IconSize - 2 * Padding) * 0.8);
p.drawText(QPoint(2 * Padding + IconSize, top_y), name);
if (!isPressed_) {
QPen pen(QColor("#5d6565"));
p.setPen(pen);
}
if (!isPressed_) {
QPen pen(QColor("#5d6565"));
p.setPen(pen);
}
font.setPixelSize(conf::fontSize);
p.setFont(font);
font.setPixelSize(conf::fontSize);
p.setFont(font);
auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5;
auto msgStampWidth = QFontMetrics(font).width(lastMsgInfo_.timestamp) + 5;
// The limit is the space between the end of the avatar and the start of the timestamp.
int usernameLimit = std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20);
auto userName = metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit);
// The limit is the space between the end of the avatar and the start of the
// timestamp.
int usernameLimit =
std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - 20);
auto userName =
metrics.elidedText(lastMsgInfo_.username, Qt::ElideRight, usernameLimit);
font.setBold(true);
p.setFont(font);
p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName);
font.setBold(true);
p.setFont(font);
p.drawText(QPoint(2 * Padding + IconSize, bottom_y), userName);
int nameWidth = QFontMetrics(font).width(userName);
int nameWidth = QFontMetrics(font).width(userName);
font.setBold(false);
p.setFont(font);
font.setBold(false);
p.setFont(font);
// The limit is the space between the end of the username and the start of the timestamp.
int descriptionLimit = std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5);
auto description = metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit);
p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y), description);
// The limit is the space between the end of the username and the start of the
// timestamp.
int descriptionLimit =
std::max(0, width() - 3 * Padding - msgStampWidth - IconSize - nameWidth - 5);
auto description =
metrics.elidedText(lastMsgInfo_.body, Qt::ElideRight, descriptionLimit);
p.drawText(QPoint(2 * Padding + IconSize + nameWidth, bottom_y), description);
// We either show the bubble or the last message timestamp.
if (unreadMsgCount_ == 0) {
font.setBold(true);
p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y), lastMsgInfo_.timestamp);
}
}
// We either show the bubble or the last message timestamp.
if (unreadMsgCount_ == 0) {
font.setBold(true);
p.drawText(QPoint(width() - Padding - msgStampWidth, bottom_y),
lastMsgInfo_.timestamp);
}
}
font.setBold(false);
p.setPen(Qt::NoPen);
font.setBold(false);
p.setPen(Qt::NoPen);
// We using the first letter of room's name.
if (roomAvatar_.isNull()) {
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor("#eee");
// We using the first letter of room's name.
if (roomAvatar_.isNull()) {
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor("#eee");
p.setPen(Qt::NoPen);
p.setBrush(brush);
p.setPen(Qt::NoPen);
p.setBrush(brush);
p.drawEllipse(avatarRegion.center(), IconSize / 2, IconSize / 2);
p.drawEllipse(avatarRegion.center(), IconSize / 2, IconSize / 2);
font.setPixelSize(conf::roomlist::fonts::bubble);
p.setFont(font);
p.setPen(QColor("#333"));
p.setBrush(Qt::NoBrush);
p.drawText(avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(state_.getName()[0]));
} else {
p.save();
font.setPixelSize(conf::roomlist::fonts::bubble);
p.setFont(font);
p.setPen(QColor("#333"));
p.setBrush(Qt::NoBrush);
p.drawText(
avatarRegion.translated(0, -1), Qt::AlignCenter, QChar(state_.getName()[0]));
} else {
p.save();
QPainterPath path;
path.addEllipse(Padding, Padding, IconSize, IconSize);
p.setClipPath(path);
QPainterPath path;
path.addEllipse(Padding, Padding, IconSize, IconSize);
p.setClipPath(path);
p.drawPixmap(avatarRegion, roomAvatar_);
p.restore();
}
p.drawPixmap(avatarRegion, roomAvatar_);
p.restore();
}
if (unreadMsgCount_ > 0) {
QColor textColor("white");
QColor backgroundColor("#38A3D8");
if (unreadMsgCount_ > 0) {
QColor textColor("white");
QColor backgroundColor("#38A3D8");
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(backgroundColor);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(backgroundColor);
if (isPressed_)
brush.setColor(textColor);
if (isPressed_)
brush.setColor(textColor);
QFont unreadCountFont;
unreadCountFont.setPixelSize(conf::roomlist::fonts::badge);
unreadCountFont.setBold(true);
QFont unreadCountFont;
unreadCountFont.setPixelSize(conf::roomlist::fonts::badge);
unreadCountFont.setBold(true);
p.setBrush(brush);
p.setPen(Qt::NoPen);
p.setFont(unreadCountFont);
p.setBrush(brush);
p.setPen(Qt::NoPen);
p.setFont(unreadCountFont);
int diameter = 20;
int diameter = 20;
QRectF r(width() - diameter - Padding, bottom_y - diameter / 2 - 5, diameter, diameter);
QRectF r(
width() - diameter - Padding, bottom_y - diameter / 2 - 5, diameter, diameter);
if (width() == ui::sidebar::SmallSize)
r = QRectF(width() - diameter - 5, height() - diameter - 5, diameter, diameter);
if (width() == ui::sidebar::SmallSize)
r = QRectF(
width() - diameter - 5, height() - diameter - 5, diameter, diameter);
p.setPen(Qt::NoPen);
p.drawEllipse(r);
p.setPen(Qt::NoPen);
p.drawEllipse(r);
p.setPen(QPen(textColor));
p.setPen(QPen(textColor));
if (isPressed_)
p.setPen(QPen(backgroundColor));
if (isPressed_)
p.setPen(QPen(backgroundColor));
p.setBrush(Qt::NoBrush);
p.drawText(r.translated(0, -0.5), Qt::AlignCenter, QString::number(unreadMsgCount_));
}
p.setBrush(Qt::NoBrush);
p.drawText(
r.translated(0, -0.5), Qt::AlignCenter, QString::number(unreadMsgCount_));
}
}
void
RoomInfoListItem::updateUnreadMessageCount(int count)
{
unreadMsgCount_ += count;
update();
unreadMsgCount_ += count;
update();
}
void
RoomInfoListItem::clearUnreadMessageCount()
{
unreadMsgCount_ = 0;
update();
unreadMsgCount_ = 0;
update();
}
void
RoomInfoListItem::setPressedState(bool state)
{
if (!isPressed_ && state) {
isPressed_ = state;
update();
} else if (isPressed_ && !state) {
isPressed_ = state;
update();
}
if (!isPressed_ && state) {
isPressed_ = state;
update();
} else if (isPressed_ && !state) {
isPressed_ = state;
update();
}
}
void
RoomInfoListItem::setState(const RoomState &new_state)
{
state_ = new_state;
update();
state_ = new_state;
update();
}
void
RoomInfoListItem::contextMenuEvent(QContextMenuEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event);
toggleNotifications_->setText(notificationText());
menu_->popup(event->globalPos());
toggleNotifications_->setText(notificationText());
menu_->popup(event->globalPos());
}
void
RoomInfoListItem::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() == Qt::RightButton) {
QWidget::mousePressEvent(event);
return;
}
if (event->buttons() == Qt::RightButton) {
QWidget::mousePressEvent(event);
return;
}
emit clicked(roomId_);
emit clicked(roomId_);
setPressedState(true);
setPressedState(true);
// Ripple on mouse position by default.
QPoint pos = event->pos();
qreal radiusEndValue = static_cast<qreal>(width()) / 3;
// Ripple on mouse position by default.
QPoint pos = event->pos();
qreal radiusEndValue = static_cast<qreal>(width()) / 3;
Ripple *ripple = new Ripple(pos);
Ripple *ripple = new Ripple(pos);
ripple->setRadiusEndValue(radiusEndValue);
ripple->setOpacityStartValue(0.15);
ripple->setColor(QColor("white"));
ripple->radiusAnimation()->setDuration(200);
ripple->opacityAnimation()->setDuration(400);
ripple->setRadiusEndValue(radiusEndValue);
ripple->setOpacityStartValue(0.15);
ripple->setColor(QColor("white"));
ripple->radiusAnimation()->setDuration(200);
ripple->opacityAnimation()->setDuration(400);
ripple_overlay_->addRipple(ripple);
ripple_overlay_->addRipple(ripple);
}
RoomInfoListItem::~RoomInfoListItem()

View file

@ -27,38 +27,38 @@ RoomList::RoomList(QSharedPointer<MatrixClient> client, QWidget *parent)
: QWidget(parent)
, client_(client)
{
setStyleSheet("QWidget { border: none; }");
setStyleSheet("QWidget { border: none; }");
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
setSizePolicy(sizePolicy);
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
setSizePolicy(sizePolicy);
topLayout_ = new QVBoxLayout(this);
topLayout_->setSpacing(0);
topLayout_->setMargin(0);
topLayout_ = new QVBoxLayout(this);
topLayout_->setSpacing(0);
topLayout_->setMargin(0);
scrollArea_ = new QScrollArea(this);
scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
scrollArea_->setWidgetResizable(true);
scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
scrollArea_ = new QScrollArea(this);
scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
scrollArea_->setWidgetResizable(true);
scrollArea_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
scrollAreaContents_ = new QWidget();
scrollAreaContents_ = new QWidget();
contentsLayout_ = new QVBoxLayout(scrollAreaContents_);
contentsLayout_->setSpacing(0);
contentsLayout_->setMargin(0);
contentsLayout_->addStretch(1);
contentsLayout_ = new QVBoxLayout(scrollAreaContents_);
contentsLayout_->setSpacing(0);
contentsLayout_->setMargin(0);
contentsLayout_->addStretch(1);
scrollArea_->setWidget(scrollAreaContents_);
topLayout_->addWidget(scrollArea_);
scrollArea_->setWidget(scrollAreaContents_);
topLayout_->addWidget(scrollArea_);
connect(client_.data(),
SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
this,
SLOT(updateRoomAvatar(const QString &, const QPixmap &)));
connect(client_.data(),
SIGNAL(roomAvatarRetrieved(const QString &, const QPixmap &)),
this,
SLOT(updateRoomAvatar(const QString &, const QPixmap &)));
}
RoomList::~RoomList()
@ -68,137 +68,140 @@ RoomList::~RoomList()
void
RoomList::clear()
{
rooms_.clear();
rooms_.clear();
}
void
RoomList::updateUnreadMessageCount(const QString &roomid, int count)
{
if (!rooms_.contains(roomid)) {
qWarning() << "UpdateUnreadMessageCount: Unknown roomid";
return;
}
if (!rooms_.contains(roomid)) {
qWarning() << "UpdateUnreadMessageCount: Unknown roomid";
return;
}
rooms_[roomid]->updateUnreadMessageCount(count);
rooms_[roomid]->updateUnreadMessageCount(count);
calculateUnreadMessageCount();
calculateUnreadMessageCount();
}
void
RoomList::calculateUnreadMessageCount()
{
int total_unread_msgs = 0;
int total_unread_msgs = 0;
for (const auto &room : rooms_)
total_unread_msgs += room->unreadMessageCount();
for (const auto &room : rooms_)
total_unread_msgs += room->unreadMessageCount();
emit totalUnreadMessageCountUpdated(total_unread_msgs);
emit totalUnreadMessageCountUpdated(total_unread_msgs);
}
void
RoomList::setInitialRooms(const QMap<QString, QSharedPointer<RoomSettings>> &settings,
const QMap<QString, RoomState> &states)
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;
}
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++) {
auto room_id = it.key();
auto state = it.value();
for (auto it = states.constBegin(); it != states.constEnd(); it++) {
auto room_id = it.key();
auto state = it.value();
if (!state.getAvatar().toString().isEmpty())
client_->fetchRoomAvatar(room_id, state.getAvatar());
if (!state.getAvatar().toString().isEmpty())
client_->fetchRoomAvatar(room_id, state.getAvatar());
RoomInfoListItem *room_item = new RoomInfoListItem(settings[room_id], state, room_id, scrollArea_);
connect(room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
RoomInfoListItem *room_item =
new RoomInfoListItem(settings[room_id], state, room_id, scrollArea_);
connect(
room_item, &RoomInfoListItem::clicked, this, &RoomList::highlightSelectedRoom);
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
rooms_.insert(room_id, QSharedPointer<RoomInfoListItem>(room_item));
int pos = contentsLayout_->count() - 1;
contentsLayout_->insertWidget(pos, room_item);
}
int pos = contentsLayout_->count() - 1;
contentsLayout_->insertWidget(pos, room_item);
}
if (rooms_.isEmpty())
return;
if (rooms_.isEmpty())
return;
auto first_room = rooms_.first();
first_room->setPressedState(true);
auto first_room = rooms_.first();
first_room->setPressedState(true);
emit roomChanged(rooms_.firstKey());
emit roomChanged(rooms_.firstKey());
}
void
RoomList::sync(const QMap<QString, RoomState> &states)
{
for (auto it = states.constBegin(); it != states.constEnd(); it++) {
auto room_id = it.key();
auto state = it.value();
for (auto it = states.constBegin(); it != states.constEnd(); it++) {
auto room_id = it.key();
auto state = it.value();
// TODO: Add the new room to the list.
if (!rooms_.contains(room_id))
continue;
// TODO: Add the new room to the list.
if (!rooms_.contains(room_id))
continue;
auto room = rooms_[room_id];
auto room = rooms_[room_id];
auto current_avatar = room->state().getAvatar();
auto new_avatar = state.getAvatar();
auto current_avatar = room->state().getAvatar();
auto new_avatar = state.getAvatar();
if (current_avatar != new_avatar && !new_avatar.toString().isEmpty())
client_->fetchRoomAvatar(room_id, new_avatar);
if (current_avatar != new_avatar && !new_avatar.toString().isEmpty())
client_->fetchRoomAvatar(room_id, new_avatar);
room->setState(state);
}
room->setState(state);
}
}
void
RoomList::highlightSelectedRoom(const QString &room_id)
{
emit roomChanged(room_id);
emit roomChanged(room_id);
if (!rooms_.contains(room_id)) {
qDebug() << "RoomList: clicked unknown roomid";
return;
}
if (!rooms_.contains(room_id)) {
qDebug() << "RoomList: clicked unknown roomid";
return;
}
// TODO: Send a read receipt for the last event.
auto room = rooms_[room_id];
room->clearUnreadMessageCount();
// TODO: Send a read receipt for the last event.
auto room = rooms_[room_id];
room->clearUnreadMessageCount();
calculateUnreadMessageCount();
calculateUnreadMessageCount();
for (auto it = rooms_.constBegin(); it != rooms_.constEnd(); it++) {
if (it.key() != room_id) {
it.value()->setPressedState(false);
} else {
it.value()->setPressedState(true);
scrollArea_->ensureWidgetVisible(qobject_cast<QWidget *>(it.value().data()));
}
}
for (auto it = rooms_.constBegin(); it != rooms_.constEnd(); it++) {
if (it.key() != room_id) {
it.value()->setPressedState(false);
} else {
it.value()->setPressedState(true);
scrollArea_->ensureWidgetVisible(
qobject_cast<QWidget *>(it.value().data()));
}
}
}
void
RoomList::updateRoomAvatar(const QString &roomid, const QPixmap &img)
{
if (!rooms_.contains(roomid)) {
qWarning() << "Avatar update on non existent room" << roomid;
return;
}
if (!rooms_.contains(roomid)) {
qWarning() << "Avatar update on non existent room" << roomid;
return;
}
rooms_.value(roomid)->setAvatar(img.toImage());
rooms_.value(roomid)->setAvatar(img.toImage());
}
void
RoomList::updateRoomDescription(const QString &roomid, const DescInfo &info)
{
if (!rooms_.contains(roomid)) {
qWarning() << "Description update on non existent room" << roomid << info.body;
return;
}
if (!rooms_.contains(roomid)) {
qWarning() << "Description update on non existent room" << roomid << info.body;
return;
}
rooms_.value(roomid)->setDescriptionMessage(info);
rooms_.value(roomid)->setDescriptionMessage(info);
}

View file

@ -20,24 +20,24 @@
void
RoomMessages::deserialize(const QJsonDocument &data)
{
if (!data.isObject())
throw DeserializationException("response is not a JSON object");
if (!data.isObject())
throw DeserializationException("response is not a JSON object");
QJsonObject object = data.object();
QJsonObject object = data.object();
if (!object.contains("start"))
throw DeserializationException("start key is missing");
if (!object.contains("start"))
throw DeserializationException("start key is missing");
if (!object.contains("end"))
throw DeserializationException("end key is missing");
if (!object.contains("end"))
throw DeserializationException("end key is missing");
if (!object.contains("chunk"))
throw DeserializationException("chunk key is missing");
if (!object.contains("chunk"))
throw DeserializationException("chunk key is missing");
if (!object.value("chunk").isArray())
throw DeserializationException("chunk isn't a JSON array");
if (!object.value("chunk").isArray())
throw DeserializationException("chunk isn't a JSON array");
start_ = object.value("start").toString();
end_ = object.value("end").toString();
chunk_ = object.value("chunk").toArray();
start_ = object.value("start").toString();
end_ = object.value("end").toString();
chunk_ = object.value("chunk").toArray();
}

View file

@ -20,19 +20,19 @@
SlidingStackWidget::SlidingStackWidget(QWidget *parent)
: QStackedWidget(parent)
{
window_ = parent;
window_ = parent;
if (parent == Q_NULLPTR) {
qDebug() << "Using nullptr for parent";
window_ = this;
}
if (parent == Q_NULLPTR) {
qDebug() << "Using nullptr for parent";
window_ = this;
}
current_position_ = QPoint(0, 0);
speed_ = 400;
now_ = 0;
next_ = 0;
active_ = false;
animation_type_ = QEasingCurve::InOutCirc;
current_position_ = QPoint(0, 0);
speed_ = 400;
now_ = 0;
next_ = 0;
active_ = false;
animation_type_ = QEasingCurve::InOutCirc;
}
SlidingStackWidget::~SlidingStackWidget()
@ -42,116 +42,116 @@ SlidingStackWidget::~SlidingStackWidget()
void
SlidingStackWidget::slideInNext()
{
int now = currentIndex();
int now = currentIndex();
if (now < count() - 1)
slideInIndex(now + 1);
if (now < count() - 1)
slideInIndex(now + 1);
}
void
SlidingStackWidget::slideInPrevious()
{
int now = currentIndex();
int now = currentIndex();
if (now > 0)
slideInIndex(now - 1);
if (now > 0)
slideInIndex(now - 1);
}
void
SlidingStackWidget::slideInIndex(int index, AnimationDirection direction)
{
// Take into consideration possible index overflow/undeflow.
if (index > count() - 1) {
direction = AnimationDirection::RIGHT_TO_LEFT;
index = index % count();
} else if (index < 0) {
direction = AnimationDirection::LEFT_TO_RIGHT;
index = (index + count()) % count();
}
// Take into consideration possible index overflow/undeflow.
if (index > count() - 1) {
direction = AnimationDirection::RIGHT_TO_LEFT;
index = index % count();
} else if (index < 0) {
direction = AnimationDirection::LEFT_TO_RIGHT;
index = (index + count()) % count();
}
slideInWidget(widget(index), direction);
slideInWidget(widget(index), direction);
}
void
SlidingStackWidget::slideInWidget(QWidget *next_widget, AnimationDirection direction)
{
// If an animation is currenlty executing we should wait for it to finish before
// another transition can start.
if (active_)
return;
// If an animation is currenlty executing we should wait for it to finish before
// another transition can start.
if (active_)
return;
active_ = true;
active_ = true;
int now = currentIndex();
int next = indexOf(next_widget);
int now = currentIndex();
int next = indexOf(next_widget);
if (now == next) {
active_ = false;
return;
}
if (now == next) {
active_ = false;
return;
}
int offset_x = frameRect().width();
int offset_x = frameRect().width();
next_widget->setGeometry(0, 0, offset_x, 0);
next_widget->setGeometry(0, 0, offset_x, 0);
if (direction == AnimationDirection::LEFT_TO_RIGHT) {
offset_x = -offset_x;
}
if (direction == AnimationDirection::LEFT_TO_RIGHT) {
offset_x = -offset_x;
}
QPoint pnext = next_widget->pos();
QPoint pnow = widget(now)->pos();
current_position_ = pnow;
QPoint pnext = next_widget->pos();
QPoint pnow = widget(now)->pos();
current_position_ = pnow;
// Reposition the next widget outside of the display area.
next_widget->move(pnext.x() - offset_x, pnext.y());
// Reposition the next widget outside of the display area.
next_widget->move(pnext.x() - offset_x, pnext.y());
// Make the widget visible.
next_widget->show();
next_widget->raise();
// Make the widget visible.
next_widget->show();
next_widget->raise();
// Animate both the next and now widget.
QPropertyAnimation *animation_now = new QPropertyAnimation(widget(now), "pos", this);
// Animate both the next and now widget.
QPropertyAnimation *animation_now = new QPropertyAnimation(widget(now), "pos", this);
animation_now->setDuration(speed_);
animation_now->setEasingCurve(animation_type_);
animation_now->setStartValue(QPoint(pnow.x(), pnow.y()));
animation_now->setEndValue(QPoint(pnow.x() + offset_x, pnow.y()));
animation_now->setDuration(speed_);
animation_now->setEasingCurve(animation_type_);
animation_now->setStartValue(QPoint(pnow.x(), pnow.y()));
animation_now->setEndValue(QPoint(pnow.x() + offset_x, pnow.y()));
QPropertyAnimation *animation_next = new QPropertyAnimation(next_widget, "pos", this);
QPropertyAnimation *animation_next = new QPropertyAnimation(next_widget, "pos", this);
animation_next->setDuration(speed_);
animation_next->setEasingCurve(animation_type_);
animation_next->setStartValue(QPoint(pnext.x() - offset_x, pnext.y()));
animation_next->setEndValue(QPoint(pnext.x(), pnext.y()));
animation_next->setDuration(speed_);
animation_next->setEasingCurve(animation_type_);
animation_next->setStartValue(QPoint(pnext.x() - offset_x, pnext.y()));
animation_next->setEndValue(QPoint(pnext.x(), pnext.y()));
QParallelAnimationGroup *animation_group = new QParallelAnimationGroup(this);
QParallelAnimationGroup *animation_group = new QParallelAnimationGroup(this);
animation_group->addAnimation(animation_now);
animation_group->addAnimation(animation_next);
animation_group->addAnimation(animation_now);
animation_group->addAnimation(animation_next);
connect(animation_group, SIGNAL(finished()), this, SLOT(onAnimationFinished()));
connect(animation_group, SIGNAL(finished()), this, SLOT(onAnimationFinished()));
next_ = next;
now_ = now;
animation_group->start();
next_ = next;
now_ = now;
animation_group->start();
}
void
SlidingStackWidget::onAnimationFinished()
{
setCurrentIndex(next_);
setCurrentIndex(next_);
// The old widget is no longer necessary so we can hide it and
// move it back to its original position.
widget(now_)->hide();
widget(now_)->move(current_position_);
// The old widget is no longer necessary so we can hide it and
// move it back to its original position.
widget(now_)->hide();
widget(now_)->move(current_position_);
active_ = false;
emit animationFinished();
active_ = false;
emit animationFinished();
}
int
SlidingStackWidget::getWidgetIndex(QWidget *widget)
{
return indexOf(widget);
return indexOf(widget);
}

View file

@ -23,59 +23,59 @@
Splitter::Splitter(QWidget *parent)
: QSplitter(parent)
{
connect(this, &QSplitter::splitterMoved, this, &Splitter::onSplitterMoved);
setChildrenCollapsible(false);
connect(this, &QSplitter::splitterMoved, this, &Splitter::onSplitterMoved);
setChildrenCollapsible(false);
}
void
Splitter::onSplitterMoved(int pos, int index)
{
Q_UNUSED(pos);
Q_UNUSED(index);
Q_UNUSED(pos);
Q_UNUSED(index);
auto s = sizes();
auto s = sizes();
if (s.count() < 2) {
qWarning() << "Splitter needs at least two children";
return;
}
if (s.count() < 2) {
qWarning() << "Splitter needs at least two children";
return;
}
if (s[0] == ui::sidebar::NormalSize) {
rightMoveCount_ += 1;
if (s[0] == ui::sidebar::NormalSize) {
rightMoveCount_ += 1;
if (rightMoveCount_ > moveEventLimit_) {
auto left = widget(0);
auto pos = left->mapFromGlobal(QCursor::pos());
if (rightMoveCount_ > moveEventLimit_) {
auto left = widget(0);
auto pos = left->mapFromGlobal(QCursor::pos());
// if we are coming from the right, the cursor should
// end up on the first widget.
if (left->rect().contains(pos)) {
left->setMinimumWidth(ui::sidebar::SmallSize);
left->setMaximumWidth(ui::sidebar::SmallSize);
// if we are coming from the right, the cursor should
// end up on the first widget.
if (left->rect().contains(pos)) {
left->setMinimumWidth(ui::sidebar::SmallSize);
left->setMaximumWidth(ui::sidebar::SmallSize);
rightMoveCount_ = 0;
}
}
} else if (s[0] == ui::sidebar::SmallSize) {
leftMoveCount_ += 1;
rightMoveCount_ = 0;
}
}
} else if (s[0] == ui::sidebar::SmallSize) {
leftMoveCount_ += 1;
if (leftMoveCount_ > moveEventLimit_) {
auto left = widget(0);
auto right = widget(1);
auto pos = right->mapFromGlobal(QCursor::pos());
if (leftMoveCount_ > moveEventLimit_) {
auto left = widget(0);
auto right = widget(1);
auto pos = right->mapFromGlobal(QCursor::pos());
// We move the start a little further so the transition isn't so abrupt.
auto extended = right->rect();
extended.translate(100, 0);
// We move the start a little further so the transition isn't so abrupt.
auto extended = right->rect();
extended.translate(100, 0);
// if we are coming from the left, the cursor should
// end up on the second widget.
if (extended.contains(pos)) {
left->setMinimumWidth(ui::sidebar::NormalSize);
left->setMaximumWidth(2 * ui::sidebar::NormalSize);
// if we are coming from the left, the cursor should
// end up on the second widget.
if (extended.contains(pos)) {
left->setMinimumWidth(ui::sidebar::NormalSize);
left->setMaximumWidth(2 * ui::sidebar::NormalSize);
leftMoveCount_ = 0;
}
}
}
leftMoveCount_ = 0;
}
}
}
}

View file

@ -27,166 +27,166 @@
void
SyncResponse::deserialize(const QJsonDocument &data)
{
if (!data.isObject())
throw DeserializationException("Sync response is not a JSON object");
if (!data.isObject())
throw DeserializationException("Sync response is not a JSON object");
QJsonObject object = data.object();
QJsonObject object = data.object();
if (object.value("next_batch") == QJsonValue::Undefined)
throw DeserializationException("Sync: missing next_batch parameter");
if (object.value("next_batch") == QJsonValue::Undefined)
throw DeserializationException("Sync: missing next_batch parameter");
if (object.value("rooms") == QJsonValue::Undefined)
throw DeserializationException("Sync: missing rooms parameter");
if (object.value("rooms") == QJsonValue::Undefined)
throw DeserializationException("Sync: missing rooms parameter");
rooms_.deserialize(object.value("rooms"));
next_batch_ = object.value("next_batch").toString();
rooms_.deserialize(object.value("rooms"));
next_batch_ = object.value("next_batch").toString();
}
void
Rooms::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("Rooms value is not a JSON object");
if (!data.isObject())
throw DeserializationException("Rooms value is not a JSON object");
QJsonObject object = data.toObject();
QJsonObject object = data.toObject();
if (!object.contains("join"))
throw DeserializationException("rooms/join is missing");
if (!object.contains("join"))
throw DeserializationException("rooms/join is missing");
if (!object.contains("invite"))
throw DeserializationException("rooms/invite is missing");
if (!object.contains("invite"))
throw DeserializationException("rooms/invite is missing");
if (!object.contains("leave"))
throw DeserializationException("rooms/leave is missing");
if (!object.contains("leave"))
throw DeserializationException("rooms/leave is missing");
if (!object.value("join").isObject())
throw DeserializationException("rooms/join must be a JSON object");
if (!object.value("join").isObject())
throw DeserializationException("rooms/join must be a JSON object");
if (!object.value("invite").isObject())
throw DeserializationException("rooms/invite must be a JSON object");
if (!object.value("invite").isObject())
throw DeserializationException("rooms/invite must be a JSON object");
if (!object.value("leave").isObject())
throw DeserializationException("rooms/leave must be a JSON object");
if (!object.value("leave").isObject())
throw DeserializationException("rooms/leave must be a JSON object");
auto join = object.value("join").toObject();
auto join = object.value("join").toObject();
for (auto it = join.constBegin(); it != join.constEnd(); it++) {
JoinedRoom tmp_room;
for (auto it = join.constBegin(); it != join.constEnd(); it++) {
JoinedRoom tmp_room;
try {
tmp_room.deserialize(it.value());
join_.insert(it.key(), tmp_room);
} catch (DeserializationException &e) {
qWarning() << e.what();
qWarning() << "Skipping malformed object for room" << it.key();
}
}
try {
tmp_room.deserialize(it.value());
join_.insert(it.key(), tmp_room);
} catch (DeserializationException &e) {
qWarning() << e.what();
qWarning() << "Skipping malformed object for room" << it.key();
}
}
}
void
JoinedRoom::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("JoinedRoom is not a JSON object");
if (!data.isObject())
throw DeserializationException("JoinedRoom is not a JSON object");
QJsonObject object = data.toObject();
QJsonObject object = data.toObject();
if (!object.contains("state"))
throw DeserializationException("join/state is missing");
if (!object.contains("state"))
throw DeserializationException("join/state is missing");
if (!object.contains("timeline"))
throw DeserializationException("join/timeline is missing");
if (!object.contains("timeline"))
throw DeserializationException("join/timeline is missing");
if (!object.contains("account_data"))
throw DeserializationException("join/account_data is missing");
if (!object.contains("account_data"))
throw DeserializationException("join/account_data is missing");
if (!object.contains("unread_notifications"))
throw DeserializationException("join/unread_notifications is missing");
if (!object.contains("unread_notifications"))
throw DeserializationException("join/unread_notifications is missing");
if (!object.value("state").isObject())
throw DeserializationException("join/state should be an object");
if (!object.value("state").isObject())
throw DeserializationException("join/state should be an object");
QJsonObject state = object.value("state").toObject();
QJsonObject state = object.value("state").toObject();
if (!state.contains("events"))
throw DeserializationException("join/state/events is missing");
if (!state.contains("events"))
throw DeserializationException("join/state/events is missing");
state_.deserialize(state.value("events"));
timeline_.deserialize(object.value("timeline"));
state_.deserialize(state.value("events"));
timeline_.deserialize(object.value("timeline"));
}
void
Event::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("Event is not a JSON object");
if (!data.isObject())
throw DeserializationException("Event is not a JSON object");
QJsonObject object = data.toObject();
QJsonObject object = data.toObject();
if (!object.contains("content"))
throw DeserializationException("event/content is missing");
if (!object.contains("content"))
throw DeserializationException("event/content is missing");
if (!object.contains("unsigned"))
throw DeserializationException("event/content is missing");
if (!object.contains("unsigned"))
throw DeserializationException("event/content is missing");
if (!object.contains("sender"))
throw DeserializationException("event/sender is missing");
if (!object.contains("sender"))
throw DeserializationException("event/sender is missing");
if (!object.contains("event_id"))
throw DeserializationException("event/event_id is missing");
if (!object.contains("event_id"))
throw DeserializationException("event/event_id is missing");
// TODO: Make this optional
/* if (!object.contains("state_key")) */
/* throw DeserializationException("event/state_key is missing"); */
// TODO: Make this optional
/* if (!object.contains("state_key")) */
/* throw DeserializationException("event/state_key is missing"); */
if (!object.contains("type"))
throw DeserializationException("event/type is missing");
if (!object.contains("type"))
throw DeserializationException("event/type is missing");
if (!object.contains("origin_server_ts"))
throw DeserializationException("event/origin_server_ts is missing");
if (!object.contains("origin_server_ts"))
throw DeserializationException("event/origin_server_ts is missing");
content_ = object.value("content").toObject();
unsigned_ = object.value("unsigned").toObject();
content_ = object.value("content").toObject();
unsigned_ = object.value("unsigned").toObject();
sender_ = object.value("sender").toString();
state_key_ = object.value("state_key").toString();
type_ = object.value("type").toString();
event_id_ = object.value("event_id").toString();
sender_ = object.value("sender").toString();
state_key_ = object.value("state_key").toString();
type_ = object.value("type").toString();
event_id_ = object.value("event_id").toString();
origin_server_ts_ = object.value("origin_server_ts").toDouble();
origin_server_ts_ = object.value("origin_server_ts").toDouble();
}
void
State::deserialize(const QJsonValue &data)
{
if (!data.isArray())
throw DeserializationException("State is not a JSON array");
if (!data.isArray())
throw DeserializationException("State is not a JSON array");
events_ = data.toArray();
events_ = data.toArray();
}
void
Timeline::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("Timeline is not a JSON object");
if (!data.isObject())
throw DeserializationException("Timeline is not a JSON object");
auto object = data.toObject();
auto object = data.toObject();
if (!object.contains("events"))
throw DeserializationException("timeline/events is missing");
if (!object.contains("events"))
throw DeserializationException("timeline/events is missing");
if (!object.contains("prev_batch"))
throw DeserializationException("timeline/prev_batch is missing");
if (!object.contains("prev_batch"))
throw DeserializationException("timeline/prev_batch is missing");
if (!object.contains("limited"))
throw DeserializationException("timeline/limited is missing");
if (!object.contains("limited"))
throw DeserializationException("timeline/limited is missing");
prev_batch_ = object.value("prev_batch").toString();
limited_ = object.value("limited").toBool();
prev_batch_ = object.value("prev_batch").toString();
limited_ = object.value("limited").toBool();
if (!object.value("events").isArray())
throw DeserializationException("timeline/events is not a JSON array");
if (!object.value("events").isArray())
throw DeserializationException("timeline/events is not a JSON array");
events_ = object.value("events").toArray();
events_ = object.value("events").toArray();
}

View file

@ -27,69 +27,75 @@
MsgCountComposedIcon::MsgCountComposedIcon(const QString &filename)
: QIconEngine()
{
icon_ = QIcon(filename);
icon_ = QIcon(filename);
}
void
MsgCountComposedIcon::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
MsgCountComposedIcon::paint(QPainter *painter,
const QRect &rect,
QIcon::Mode mode,
QIcon::State state)
{
painter->setRenderHint(QPainter::TextAntialiasing);
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::Antialiasing);
painter->setRenderHint(QPainter::TextAntialiasing);
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::Antialiasing);
icon_.paint(painter, rect, Qt::AlignCenter, mode, state);
icon_.paint(painter, rect, Qt::AlignCenter, mode, state);
if (msgCount <= 0)
return;
if (msgCount <= 0)
return;
QColor backgroundColor("red");
QColor textColor("white");
QColor backgroundColor("red");
QColor textColor("white");
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(backgroundColor);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(backgroundColor);
painter->setBrush(brush);
painter->setPen(Qt::NoPen);
painter->setFont(QFont("Open Sans", 8, QFont::Black));
painter->setBrush(brush);
painter->setPen(Qt::NoPen);
painter->setFont(QFont("Open Sans", 8, QFont::Black));
QRectF bubble(rect.width() - BubbleDiameter, rect.height() - BubbleDiameter, BubbleDiameter, BubbleDiameter);
painter->drawEllipse(bubble);
painter->setPen(QPen(textColor));
painter->setBrush(Qt::NoBrush);
painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount));
QRectF bubble(rect.width() - BubbleDiameter,
rect.height() - BubbleDiameter,
BubbleDiameter,
BubbleDiameter);
painter->drawEllipse(bubble);
painter->setPen(QPen(textColor));
painter->setBrush(Qt::NoBrush);
painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount));
}
QIconEngine *
MsgCountComposedIcon::clone() const
{
return new MsgCountComposedIcon(*this);
return new MsgCountComposedIcon(*this);
}
TrayIcon::TrayIcon(const QString &filename, QWidget *parent)
: QSystemTrayIcon(parent)
{
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
setIcon(QIcon(filename));
setIcon(QIcon(filename));
#else
icon_ = new MsgCountComposedIcon(filename);
setIcon(QIcon(icon_));
icon_ = new MsgCountComposedIcon(filename);
setIcon(QIcon(icon_));
#endif
QMenu *menu = new QMenu(parent);
viewAction_ = new QAction(tr("Show"), parent);
quitAction_ = new QAction(tr("Quit"), parent);
QMenu *menu = new QMenu(parent);
viewAction_ = new QAction(tr("Show"), parent);
quitAction_ = new QAction(tr("Quit"), parent);
connect(viewAction_, SIGNAL(triggered()), parent, SLOT(show()));
connect(quitAction_, &QAction::triggered, this, [=]() { QApplication::quit(); });
connect(viewAction_, SIGNAL(triggered()), parent, SLOT(show()));
connect(quitAction_, &QAction::triggered, this, [=]() { QApplication::quit(); });
menu->addAction(viewAction_);
menu->addAction(quitAction_);
menu->addAction(viewAction_);
menu->addAction(quitAction_);
setContextMenu(menu);
setContextMenu(menu);
// We wait a little for the icon to load.
QTimer::singleShot(500, this, [=]() { show(); });
// We wait a little for the icon to load.
QTimer::singleShot(500, this, [=]() { show(); });
}
void
@ -97,20 +103,20 @@ TrayIcon::setUnreadCount(int count)
{
// Use the native badge counter in MacOS.
#if defined(Q_OS_MAC)
if (count == 0)
QtMac::setBadgeLabelText("");
else
QtMac::setBadgeLabelText(QString::number(count));
if (count == 0)
QtMac::setBadgeLabelText("");
else
QtMac::setBadgeLabelText(QString::number(count));
#elif defined(Q_OS_WIN)
// FIXME: Find a way to use Windows apis for the badge counter (if any).
#else
// Custom drawing on Linux.
// FIXME: It doesn't seem to work on KDE.
MsgCountComposedIcon *tmp = static_cast<MsgCountComposedIcon *>(icon_->clone());
tmp->msgCount = count;
// Custom drawing on Linux.
// FIXME: It doesn't seem to work on KDE.
MsgCountComposedIcon *tmp = static_cast<MsgCountComposedIcon *>(icon_->clone());
tmp->msgCount = count;
setIcon(QIcon(tmp));
setIcon(QIcon(tmp));
icon_ = tmp;
icon_ = tmp;
#endif
}

View file

@ -31,92 +31,95 @@ UserInfoWidget::UserInfoWidget(QWidget *parent)
, logoutDialog_{ nullptr }
, logoutButtonSize_{ 32 }
{
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setSizePolicy(sizePolicy);
setMinimumSize(QSize(0, 65));
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setSizePolicy(sizePolicy);
setMinimumSize(QSize(0, 65));
topLayout_ = new QHBoxLayout(this);
topLayout_->setSpacing(0);
topLayout_->setMargin(5);
topLayout_ = new QHBoxLayout(this);
topLayout_->setSpacing(0);
topLayout_->setMargin(5);
avatarLayout_ = new QHBoxLayout();
textLayout_ = new QVBoxLayout();
avatarLayout_ = new QHBoxLayout();
textLayout_ = new QVBoxLayout();
userAvatar_ = new Avatar(this);
userAvatar_->setLetter(QChar('?'));
userAvatar_->setSize(55);
userAvatar_->setBackgroundColor("#f9f9f9");
userAvatar_->setTextColor("#333333");
userAvatar_ = new Avatar(this);
userAvatar_->setLetter(QChar('?'));
userAvatar_->setSize(55);
userAvatar_->setBackgroundColor("#f9f9f9");
userAvatar_->setTextColor("#333333");
QFont nameFont("Open Sans SemiBold");
nameFont.setPixelSize(conf::userInfoWidget::fonts::displayName);
QFont nameFont("Open Sans SemiBold");
nameFont.setPixelSize(conf::userInfoWidget::fonts::displayName);
displayNameLabel_ = new QLabel(this);
displayNameLabel_->setFont(nameFont);
displayNameLabel_->setStyleSheet("padding: 0 9px; color: #171919; margin-bottom: -10px;");
displayNameLabel_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop);
displayNameLabel_ = new QLabel(this);
displayNameLabel_->setFont(nameFont);
displayNameLabel_->setStyleSheet("padding: 0 9px; color: #171919; margin-bottom: -10px;");
displayNameLabel_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignTop);
QFont useridFont("Open Sans");
useridFont.setPixelSize(conf::userInfoWidget::fonts::userid);
QFont useridFont("Open Sans");
useridFont.setPixelSize(conf::userInfoWidget::fonts::userid);
userIdLabel_ = new QLabel(this);
userIdLabel_->setFont(useridFont);
userIdLabel_->setStyleSheet("padding: 0 8px 8px 8px; color: #555459;");
userIdLabel_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
userIdLabel_ = new QLabel(this);
userIdLabel_->setFont(useridFont);
userIdLabel_->setStyleSheet("padding: 0 8px 8px 8px; color: #555459;");
userIdLabel_->setAlignment(Qt::AlignLeading | Qt::AlignLeft | Qt::AlignVCenter);
avatarLayout_->addWidget(userAvatar_);
textLayout_->addWidget(displayNameLabel_);
textLayout_->addWidget(userIdLabel_);
avatarLayout_->addWidget(userAvatar_);
textLayout_->addWidget(displayNameLabel_);
textLayout_->addWidget(userIdLabel_);
topLayout_->addLayout(avatarLayout_);
topLayout_->addLayout(textLayout_);
topLayout_->addStretch(1);
topLayout_->addLayout(avatarLayout_);
topLayout_->addLayout(textLayout_);
topLayout_->addStretch(1);
buttonLayout_ = new QHBoxLayout();
buttonLayout_->setSpacing(0);
buttonLayout_->setMargin(0);
buttonLayout_ = new QHBoxLayout();
buttonLayout_->setSpacing(0);
buttonLayout_->setMargin(0);
logoutButton_ = new FlatButton(this);
logoutButton_->setForegroundColor(QColor("#555459"));
logoutButton_->setFixedSize(logoutButtonSize_, logoutButtonSize_);
logoutButton_->setCornerRadius(logoutButtonSize_ / 2);
logoutButton_ = new FlatButton(this);
logoutButton_->setForegroundColor(QColor("#555459"));
logoutButton_->setFixedSize(logoutButtonSize_, logoutButtonSize_);
logoutButton_->setCornerRadius(logoutButtonSize_ / 2);
QIcon icon;
icon.addFile(":/icons/icons/power-button-off.png", QSize(), QIcon::Normal, QIcon::Off);
QIcon icon;
icon.addFile(":/icons/icons/power-button-off.png", QSize(), QIcon::Normal, QIcon::Off);
logoutButton_->setIcon(icon);
logoutButton_->setIconSize(QSize(logoutButtonSize_ / 2, logoutButtonSize_ / 2));
logoutButton_->setIcon(icon);
logoutButton_->setIconSize(QSize(logoutButtonSize_ / 2, logoutButtonSize_ / 2));
buttonLayout_->addWidget(logoutButton_);
buttonLayout_->addWidget(logoutButton_);
topLayout_->addLayout(buttonLayout_);
topLayout_->addLayout(buttonLayout_);
// 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)));
}
// 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));
}
if (logoutModal_ == nullptr) {
logoutModal_ = new OverlayModal(MainWindow::instance(), logoutDialog_);
logoutModal_->setDuration(100);
logoutModal_->setColor(QColor(55, 55, 55, 170));
}
logoutModal_->fadeIn();
});
logoutModal_->fadeIn();
});
}
void
UserInfoWidget::closeLogoutDialog(bool isLoggingOut)
{
logoutModal_->fadeOut();
logoutModal_->fadeOut();
if (isLoggingOut) {
// Waiting for the modal to fade out.
QTimer::singleShot(100, this, [=]() { emit logout(); });
}
if (isLoggingOut) {
// Waiting for the modal to fade out.
QTimer::singleShot(100, this, [=]() { emit logout(); });
}
}
UserInfoWidget::~UserInfoWidget()
@ -126,52 +129,52 @@ UserInfoWidget::~UserInfoWidget()
void
UserInfoWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
Q_UNUSED(event);
if (width() <= ui::sidebar::SmallSize) {
topLayout_->setContentsMargins(0, 0, logoutButtonSize_ / 2 - 5 / 2, 0);
if (width() <= ui::sidebar::SmallSize) {
topLayout_->setContentsMargins(0, 0, logoutButtonSize_ / 2 - 5 / 2, 0);
userAvatar_->hide();
displayNameLabel_->hide();
userIdLabel_->hide();
} else {
topLayout_->setMargin(5);
userAvatar_->show();
displayNameLabel_->show();
userIdLabel_->show();
}
userAvatar_->hide();
displayNameLabel_->hide();
userIdLabel_->hide();
} else {
topLayout_->setMargin(5);
userAvatar_->show();
displayNameLabel_->show();
userIdLabel_->show();
}
}
void
UserInfoWidget::reset()
{
displayNameLabel_->setText("");
userIdLabel_->setText("");
userAvatar_->setLetter(QChar('?'));
displayNameLabel_->setText("");
userIdLabel_->setText("");
userAvatar_->setLetter(QChar('?'));
}
void
UserInfoWidget::setAvatar(const QImage &img)
{
avatar_image_ = img;
userAvatar_->setImage(img);
avatar_image_ = img;
userAvatar_->setImage(img);
}
void
UserInfoWidget::setDisplayName(const QString &name)
{
if (name.isEmpty())
display_name_ = user_id_.split(':')[0].split('@')[1];
else
display_name_ = name;
if (name.isEmpty())
display_name_ = user_id_.split(':')[0].split('@')[1];
else
display_name_ = name;
displayNameLabel_->setText(display_name_);
userAvatar_->setLetter(QChar(display_name_[0]));
displayNameLabel_->setText(display_name_);
userAvatar_->setLetter(QChar(display_name_[0]));
}
void
UserInfoWidget::setUserId(const QString &userid)
{
user_id_ = userid;
userIdLabel_->setText(userid);
user_id_ = userid;
userIdLabel_->setText(userid);
}

View file

@ -27,38 +27,39 @@
void
VersionsResponse::deserialize(const QJsonDocument &data)
{
if (!data.isObject())
throw DeserializationException("Versions response is not a JSON object");
if (!data.isObject())
throw DeserializationException("Versions response is not a JSON object");
QJsonObject object = data.object();
QJsonObject object = data.object();
if (object.value("versions") == QJsonValue::Undefined)
throw DeserializationException("Versions: missing version list");
if (object.value("versions") == QJsonValue::Undefined)
throw DeserializationException("Versions: missing version list");
auto versions = object.value("versions").toArray();
for (auto const &elem : versions) {
QString str = elem.toString();
QRegExp rx("r(\\d+)\\.(\\d+)\\.(\\d+)");
auto versions = object.value("versions").toArray();
for (auto const &elem : versions) {
QString str = elem.toString();
QRegExp rx("r(\\d+)\\.(\\d+)\\.(\\d+)");
if (rx.indexIn(str) == -1)
throw DeserializationException("Invalid version string in versions response");
if (rx.indexIn(str) == -1)
throw DeserializationException(
"Invalid version string in versions response");
struct Version_ v;
v.major_ = rx.cap(1).toUInt();
v.minor_ = rx.cap(2).toUInt();
v.patch_ = rx.cap(3).toUInt();
struct Version_ v;
v.major_ = rx.cap(1).toUInt();
v.minor_ = rx.cap(2).toUInt();
v.patch_ = rx.cap(3).toUInt();
supported_versions_.push_back(v);
}
supported_versions_.push_back(v);
}
}
bool
VersionsResponse::isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch)
{
for (auto &v : supported_versions_) {
if (v.major_ == major && v.minor_ == minor && v.patch_ >= patch)
return true;
}
for (auto &v : supported_versions_) {
if (v.major_ == major && v.minor_ == minor && v.patch_ >= patch)
return true;
}
return false;
return false;
}

View file

@ -24,78 +24,79 @@
WelcomePage::WelcomePage(QWidget *parent)
: QWidget(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
top_layout_ = new QVBoxLayout(this);
top_layout_->setSpacing(0);
top_layout_->setMargin(0);
top_layout_ = new QVBoxLayout(this);
top_layout_->setSpacing(0);
top_layout_->setMargin(0);
intro_banner_ = new QLabel(this);
intro_banner_->setPixmap(QPixmap(":/logos/nheko-256.png"));
intro_banner_->setAlignment(Qt::AlignCenter);
intro_banner_ = new QLabel(this);
intro_banner_->setPixmap(QPixmap(":/logos/nheko-256.png"));
intro_banner_->setAlignment(Qt::AlignCenter);
intro_text_ = new QLabel(this);
intro_text_ = new QLabel(this);
QString heading(tr("Welcome to nheko! The desktop client for the Matrix protocol."));
QString main(tr("Enjoy your stay!"));
QString heading(tr("Welcome to nheko! The desktop client for the Matrix protocol."));
QString main(tr("Enjoy your stay!"));
intro_text_->setText(QString("<p align=\"center\" style=\"margin: 0; line-height: 2pt\">"
" <span style=\" font-size:18px; color:#515151;\"> %1 </span>"
"</p>"
"<p align=\"center\" style=\"margin: 1pt; line-height: 2pt;\">"
" <span style=\" font-size:18px; color:#515151;\"> %2 </span>"
"</p>")
.arg(heading)
.arg(main));
intro_text_->setText(QString("<p align=\"center\" style=\"margin: 0; line-height: 2pt\">"
" <span style=\" font-size:18px; color:#515151;\"> %1 </span>"
"</p>"
"<p align=\"center\" style=\"margin: 1pt; line-height: 2pt;\">"
" <span style=\" font-size:18px; color:#515151;\"> %2 </span>"
"</p>")
.arg(heading)
.arg(main));
top_layout_->addStretch(1);
top_layout_->addWidget(intro_banner_);
top_layout_->addStretch(1);
top_layout_->addWidget(intro_text_, 0, Qt::AlignCenter);
top_layout_->addStretch(1);
top_layout_->addStretch(1);
top_layout_->addWidget(intro_banner_);
top_layout_->addStretch(1);
top_layout_->addWidget(intro_text_, 0, Qt::AlignCenter);
top_layout_->addStretch(1);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
button_layout_->setContentsMargins(0, 20, 0, 80);
button_layout_ = new QHBoxLayout();
button_layout_->setSpacing(0);
button_layout_->setContentsMargins(0, 20, 0, 80);
register_button_ = new RaisedButton(tr("REGISTER"), this);
register_button_->setBackgroundColor(QColor("#333333"));
register_button_->setForegroundColor(QColor("white"));
register_button_->setMinimumSize(240, 60);
register_button_->setFontSize(conf::btn::fontSize);
register_button_->setCornerRadius(conf::btn::cornerRadius);
register_button_ = new RaisedButton(tr("REGISTER"), this);
register_button_->setBackgroundColor(QColor("#333333"));
register_button_->setForegroundColor(QColor("white"));
register_button_->setMinimumSize(240, 60);
register_button_->setFontSize(conf::btn::fontSize);
register_button_->setCornerRadius(conf::btn::cornerRadius);
login_button_ = new RaisedButton(tr("LOGIN"), this);
login_button_->setBackgroundColor(QColor("#333333"));
login_button_->setForegroundColor(QColor("white"));
login_button_->setMinimumSize(240, 60);
login_button_->setFontSize(conf::btn::fontSize);
login_button_->setCornerRadius(conf::btn::cornerRadius);
login_button_ = new RaisedButton(tr("LOGIN"), this);
login_button_->setBackgroundColor(QColor("#333333"));
login_button_->setForegroundColor(QColor("white"));
login_button_->setMinimumSize(240, 60);
login_button_->setFontSize(conf::btn::fontSize);
login_button_->setCornerRadius(conf::btn::cornerRadius);
button_spacer_ = new QSpacerItem(20, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
button_spacer_ =
new QSpacerItem(20, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
button_layout_->addStretch(1);
button_layout_->addWidget(register_button_);
button_layout_->addItem(button_spacer_);
button_layout_->addWidget(login_button_);
button_layout_->addStretch(1);
button_layout_->addStretch(1);
button_layout_->addWidget(register_button_);
button_layout_->addItem(button_spacer_);
button_layout_->addWidget(login_button_);
button_layout_->addStretch(1);
top_layout_->addLayout(button_layout_);
top_layout_->addLayout(button_layout_);
connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
connect(login_button_, SIGNAL(clicked()), this, SLOT(onLoginButtonClicked()));
}
void
WelcomePage::onLoginButtonClicked()
{
emit userLogin();
emit userLogin();
}
void
WelcomePage::onRegisterButtonClicked()
{
emit userRegister();
emit userRegister();
}
WelcomePage::~WelcomePage()

View file

@ -24,32 +24,32 @@ using namespace matrix::events;
void
AliasesEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("AliasesEventContent is not a JSON object");
if (!data.isObject())
throw DeserializationException("AliasesEventContent is not a JSON object");
auto object = data.toObject();
auto object = data.toObject();
if (object.value("aliases") == QJsonValue::Undefined)
throw DeserializationException("aliases key is missing");
if (object.value("aliases") == QJsonValue::Undefined)
throw DeserializationException("aliases key is missing");
auto aliases = object.value("aliases").toArray();
auto aliases = object.value("aliases").toArray();
for (const auto &alias : aliases)
aliases_.push_back(alias.toString());
for (const auto &alias : aliases)
aliases_.push_back(alias.toString());
}
QJsonObject
AliasesEventContent::serialize() const
{
QJsonObject object;
QJsonObject object;
QJsonArray aliases;
QJsonArray aliases;
for (const auto &alias : aliases_)
aliases.push_back(alias);
for (const auto &alias : aliases_)
aliases.push_back(alias);
if (aliases.size() > 0)
object["aliases"] = aliases;
if (aliases.size() > 0)
object["aliases"] = aliases;
return object;
return object;
}

View file

@ -24,27 +24,27 @@ using namespace matrix::events;
void
AvatarEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("AvatarEventContent is not a JSON object");
if (!data.isObject())
throw DeserializationException("AvatarEventContent is not a JSON object");
auto object = data.toObject();
auto object = data.toObject();
if (object.value("url") == QJsonValue::Undefined)
throw DeserializationException("url key is missing");
if (object.value("url") == QJsonValue::Undefined)
throw DeserializationException("url key is missing");
url_ = QUrl(object.value("url").toString());
url_ = QUrl(object.value("url").toString());
if (!url_.isValid())
qWarning() << "Invalid avatar url" << url_;
if (!url_.isValid())
qWarning() << "Invalid avatar url" << url_;
}
QJsonObject
AvatarEventContent::serialize() const
{
QJsonObject object;
QJsonObject object;
if (!url_.isEmpty())
object["url"] = url_.toString();
if (!url_.isEmpty())
object["url"] = url_.toString();
return object;
return object;
}

View file

@ -22,24 +22,24 @@ using namespace matrix::events;
void
CanonicalAliasEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("CanonicalAliasEventContent is not a JSON object");
if (!data.isObject())
throw DeserializationException("CanonicalAliasEventContent is not a JSON object");
auto object = data.toObject();
auto object = data.toObject();
if (object.value("alias") == QJsonValue::Undefined)
throw DeserializationException("alias key is missing");
if (object.value("alias") == QJsonValue::Undefined)
throw DeserializationException("alias key is missing");
alias_ = object.value("alias").toString();
alias_ = object.value("alias").toString();
}
QJsonObject
CanonicalAliasEventContent::serialize() const
{
QJsonObject object;
QJsonObject object;
if (!alias_.isEmpty())
object["alias"] = alias_;
if (!alias_.isEmpty())
object["alias"] = alias_;
return object;
return object;
}

View file

@ -22,24 +22,24 @@ using namespace matrix::events;
void
CreateEventContent::deserialize(const QJsonValue &data)
{
if (!data.isObject())
throw DeserializationException("CreateEventContent is not a JSON object");
if (!data.isObject())
throw DeserializationException("CreateEventContent is not a JSON object");
auto object = data.toObject();
auto object = data.toObject();
if (object.value("creator") == QJsonValue::Undefined)
throw DeserializationException("creator key is missing");
if (object.value("creator") == QJsonValue::Undefined)
throw DeserializationException("creator key is missing");
creator_ = object.value("creator").toString();
creator_ = object.value("creator").toString();
}
QJsonObject
CreateEventContent::serialize() const
{
QJsonObject object;
QJsonObject object;
if (!creator_.isEmpty())
object["creator"] = creator_;
if (!creator_.isEmpty())
object["creator"] = creator_;
return object;
return object;
}

Some files were not shown because too many files have changed in this diff Show more