diff --git a/main.cpp b/main.cpp index ee65d0a..4c4b3ea 100644 --- a/main.cpp +++ b/main.cpp @@ -77,11 +77,6 @@ int main(int argc, char *argv[]) new Shared::Global(); //translates enums - // QtQuickControls2 Style - if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) { - qputenv("QT_QUICK_CONTROLS_STYLE", "Material"); - } - Squawk w; w.show(); diff --git a/resources/qml/feed.qml b/resources/qml/feed.qml deleted file mode 100644 index 3fc0ba8..0000000 --- a/resources/qml/feed.qml +++ /dev/null @@ -1,79 +0,0 @@ -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 - -ListView { - id: list - verticalLayoutDirection: ListView.BottomToTop - - required model - - delegate: RowLayout { - id: root - width: ListView.view.width - - // placeholder - Item { - Layout.preferredWidth: root.layoutDirection === Qt.LeftToRight ? 5 : 10 - } - -// Avatar { -// id: avatar -// visible: !sentByMe -// avatarUrl: root.avatarUrl -// Layout.alignment: Qt.AlignHCenter | Qt.AlignTop -// name: root.senderName -// Layout.preferredHeight: Kirigami.Units.gridUnit * 2.2 -// Layout.preferredWidth: Kirigami.Units.gridUnit * 2.2 -// } - - Item { - Layout.preferredWidth: content.width + 16 - Layout.preferredHeight: content.height + 16 - - Rectangle { - id: messageBubble - anchors.fill: parent - - color: "blue" - } - - ColumnLayout { - id: content - spacing: 5 - anchors.centerIn: parent - - Label { - text: model.sender - } - - Label { - text: model.text - wrapMode: Text.Wrap - Layout.maximumWidth: root.width - } - - // message meta data: date, deliveryState - RowLayout { - Layout.bottomMargin: -4 - - Label { - id: dateLabel - text: model.date - } - -// Icon { -// source: "edit-symbolic" -// visible: model.correction -// Layout.preferredHeight: 10 -// Layout.preferredWidth: 10 -// } - } - } - } - - Item { - Layout.fillWidth: true - } - } -} diff --git a/resources/resources.qrc b/resources/resources.qrc index 179b251..4fb3e5b 100644 --- a/resources/resources.qrc +++ b/resources/resources.qrc @@ -160,7 +160,5 @@ images/fallback/light/small/favorite.svg images/fallback/light/small/unfavorite.svg images/fallback/light/small/add.svg - - qml/feed.qml diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 4fada80..23f5f39 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -39,6 +39,7 @@ set(squawkUI_SRC utils/progress.cpp utils/comboboxdelegate.cpp utils/dropshadoweffect.cpp + utils/feedview.cpp ) # Tell CMake to create the helloworld executable diff --git a/ui/models/messagefeed.cpp b/ui/models/messagefeed.cpp index a097693..f7e6b4b 100644 --- a/ui/models/messagefeed.cpp +++ b/ui/models/messagefeed.cpp @@ -85,6 +85,7 @@ QVariant MessageFeed::data(const QModelIndex& index, int role) const const Shared::Message* msg = *itr; switch (role) { + case Qt::DisplayRole: case Text: answer = msg->getBody(); break; @@ -108,6 +109,7 @@ QVariant MessageFeed::data(const QModelIndex& index, int role) const } } else { switch (role) { + case Qt::DisplayRole: case Text: answer = "loading..."; break; diff --git a/ui/utils/feedview.cpp b/ui/utils/feedview.cpp new file mode 100644 index 0000000..fa2adbb --- /dev/null +++ b/ui/utils/feedview.cpp @@ -0,0 +1,125 @@ +/* + * Squawk messenger. + * Copyright (C) 2019 Yury Gubich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "feedview.h" + +#include +#include +#include + +FeedView::FeedView(QWidget* parent): + QAbstractItemView(parent), + hints() +{ + +} + +FeedView::~FeedView() +{ +} + +QModelIndex FeedView::indexAt(const QPoint& point) const +{ + return QModelIndex(); +} + +void FeedView::scrollTo(const QModelIndex& index, QAbstractItemView::ScrollHint hint) +{ +} + +QRect FeedView::visualRect(const QModelIndex& index) const +{ + if (!index.isValid() || index.row() >= hints.size()) { + return QRect(); + } else { + const Hint& hint = hints.at(index.row()); + const QWidget* vp = viewport(); + return QRect(0, vp->height() - hint.height - hint.offset, vp->width(), hint.height); + } +} + +int FeedView::horizontalOffset() const +{ + return 0; +} + +bool FeedView::isIndexHidden(const QModelIndex& index) const +{ + return true; +} + +QModelIndex FeedView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers) +{ + return QModelIndex(); +} + +void FeedView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags command) +{ +} + +int FeedView::verticalOffset() const +{ + return 0; +} + +QRegion FeedView::visualRegionForSelection(const QItemSelection& selection) const +{ + return QRegion(); +} + +void FeedView::rowsInserted(const QModelIndex& parent, int start, int end) +{ + scheduleDelayedItemsLayout(); + QAbstractItemView::rowsInserted(parent, start, end); +} + +void FeedView::updateGeometries() +{ + qDebug() << "updateGeometries"; + QAbstractItemView::updateGeometries(); + const QAbstractItemModel* m = model(); + QStyleOptionViewItem option = viewOptions(); + uint32_t previousOffset = 0; + + hints.clear(); + for (int i = 0, size = m->rowCount(); i < size; ++i) { + QModelIndex index = m->index(i, 0, QModelIndex()); + int height = itemDelegate(index)->sizeHint(option, index).height(); + hints.emplace_back(Hint({ + false, + previousOffset, + static_cast(height) + })); + previousOffset += height; + } +} + +void FeedView::paintEvent(QPaintEvent* event) +{ + qDebug() << "paint"; + const QAbstractItemModel* m = model(); + QRect zone = event->rect().translated(horizontalOffset(), -verticalOffset()); + QPainter painter(viewport()); + QStyleOptionViewItem option = viewOptions(); + + for (int i = 0, size = m->rowCount(); i < size; ++i) { + QModelIndex index = m->index(i, 0, QModelIndex()); + option.rect = visualRect(index); + itemDelegate(index)->paint(&painter, option, index); + } +} diff --git a/ui/utils/feedview.h b/ui/utils/feedview.h new file mode 100644 index 0000000..8cba4f7 --- /dev/null +++ b/ui/utils/feedview.h @@ -0,0 +1,65 @@ +/* + * Squawk messenger. + * Copyright (C) 2019 Yury Gubich + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FEEDVIEW_H +#define FEEDVIEW_H + +#include + +#include + +#include + +/** + * @todo write docs + */ +class FeedView : public QAbstractItemView +{ + Q_OBJECT +public: + FeedView(QWidget* parent = nullptr); + ~FeedView(); + + QModelIndex indexAt(const QPoint & point) const override; + void scrollTo(const QModelIndex & index, QAbstractItemView::ScrollHint hint) override; + QRect visualRect(const QModelIndex & index) const override; + bool isIndexHidden(const QModelIndex & index) const override; + QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override; + void setSelection(const QRect & rect, QItemSelectionModel::SelectionFlags command) override; + QRegion visualRegionForSelection(const QItemSelection & selection) const override; + +protected slots: + void rowsInserted(const QModelIndex & parent, int start, int end) override; + +protected: + int verticalOffset() const override; + int horizontalOffset() const override; + void paintEvent(QPaintEvent * event) override; + void updateGeometries() override; + +private: + struct Hint { + bool dirty; + uint32_t offset; + uint32_t height; + }; + std::deque hints; + +}; + +#endif //FEEDVIEW_H diff --git a/ui/widgets/CMakeLists.txt b/ui/widgets/CMakeLists.txt index 0932100..0a21f04 100644 --- a/ui/widgets/CMakeLists.txt +++ b/ui/widgets/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) # Find the QtWidgets library -find_package(Qt5Widgets CONFIG REQUIRED COMPONENTS Widgets Quick Qml QuickControls2 Core) +find_package(Qt5Widgets CONFIG REQUIRED COMPONENTS Widgets Core) add_subdirectory(vcard) @@ -26,7 +26,5 @@ add_library(squawkWidgets ${squawkWidgets_SRC}) # Use the Widgets module from Qt 5. target_link_libraries(squawkWidgets vCardUI) target_link_libraries(squawkWidgets Qt5::Widgets) -target_link_libraries(squawkWidgets Qt5::Qml) -target_link_libraries(squawkWidgets Qt5::QuickControls2) -qt5_use_modules(squawkWidgets Quick Qml QuickControls2 Core Widgets) +qt5_use_modules(squawkWidgets Core Widgets) diff --git a/ui/widgets/conversation.cpp b/ui/widgets/conversation.cpp index 6643865..0326ed2 100644 --- a/ui/widgets/conversation.cpp +++ b/ui/widgets/conversation.cpp @@ -45,7 +45,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el, filesLayout(0), overlay(new QWidget()), filesToAttach(), - feed(new QQuickView()), + feed(new FeedView()), scroll(down), manualSliderChange(false), requestingHistory(false), @@ -54,13 +54,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, Models::Element* el, { m_ui->setupUi(this); - feed->setColor(QWidget::palette().color(QPalette::Base)); - feed->setInitialProperties({{"model", QVariant::fromValue(el->feed)}}); - feed->setResizeMode(QQuickView::SizeRootObjectToView); - feed->setSource(QUrl("qrc:/qml/feed.qml")); - QWidget *container = QWidget::createWindowContainer(feed, this); - container->setAutoFillBackground(false); - m_ui->widget->layout()->addWidget(container); + feed->setModel(el->feed); + m_ui->widget->layout()->addWidget(feed); connect(acc, &Models::Account::childChanged, this, &Conversation::onAccountChanged); diff --git a/ui/widgets/conversation.h b/ui/widgets/conversation.h index b0e1b79..bc5863e 100644 --- a/ui/widgets/conversation.h +++ b/ui/widgets/conversation.h @@ -24,7 +24,6 @@ #include #include #include -#include #include "shared/message.h" #include "order.h" @@ -34,6 +33,7 @@ #include "ui/utils/resizer.h" #include "ui/utils/flowlayout.h" #include "ui/utils/badge.h" +#include "ui/utils/feedview.h" #include "shared/icons.h" #include "shared/utils.h" @@ -146,7 +146,7 @@ protected: FlowLayout* filesLayout; QWidget* overlay; W::Order filesToAttach; - QQuickView* feed; + FeedView* feed; Scroll scroll; bool manualSliderChange; bool requestingHistory;