diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2021-03-12 03:22:01 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2021-03-16 20:40:13 -0400 |
| commit | 2cb36d8f7ba30e1ba2b4e3566aede9016e15399f (patch) | |
| tree | 5aadc214e3a2ec97ab2b38436c7b7ad8934baac9 | |
| parent | e43222c3e8da9f42d0d95207fa94335165a27d9d (diff) | |
Add a QTextBrowser capable of showing remote images
| -rw-r--r-- | ui/textbrowser.h | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/ui/textbrowser.h b/ui/textbrowser.h new file mode 100644 index 00000000..9d4d33c3 --- /dev/null +++ b/ui/textbrowser.h @@ -0,0 +1,114 @@ +#pragma once + +#include <QtWidgets/QTextBrowser> +#include <QtGui/QTextDocument> +#include <QtGui/QTextBlock> +#include <QtGui/QTextFragment> +#include <QtGui/QImage> +#include <QtCore/QThread> +#include <QtCore/QMutex> +#include <QtCore/QWaitCondition> +#include <QtCore/QSharedPointer> +#include <queue> +#include <optional> +#include "binaryninjaapi.h" +#include "uitypes.h" + +class TextBrowser; +class TextBrowserDownloadThread; + +class BINARYNINJAUIAPI TextBrowserDownloadCache +{ + QMutex m_mutex; + std::map<QUrl, QByteArray> m_downloadCache; + std::set<QUrl> m_inProgress; + +public: + TextBrowserDownloadCache(); + + bool lookup(const QUrl& url, QByteArray& result); + void add(const QUrl& url, const QByteArray& data); + + void beginRequest(const QUrl& url); + void endRequest(const QUrl& url); + bool isInProgress(const QUrl& url); +}; + +class TextBrowserDownloadQueue: public QObject +{ + Q_OBJECT + + QMutex m_mutex; + QWaitCondition m_cond; + TextBrowser* m_owner; + + std::queue<QUrl> m_queue; + + size_t m_activeThreads = 0; + + static uint64_t AppendDataCallback(uint8_t* data, uint64_t len, void* ctxt); + +public: + TextBrowserDownloadQueue(TextBrowser* owner); + + void stop(); + void threadFinished(); + bool processNextEvent(BinaryNinja::DownloadInstance* downloadInstance); + void downloadData(const QUrl& name); + +Q_SIGNALS: + void dataDownloaded(QUrl name, QByteArray contents); +}; + +class TextBrowserDownloadThread: public QThread +{ + Q_OBJECT + + QMutex m_mutex; + TextBrowserDownloadQueue* m_queue; + + BinaryNinja::Ref<BinaryNinja::DownloadProvider> m_provider; + BinaryNinja::Ref<BinaryNinja::DownloadInstance> m_downloadInstance; + +protected: + virtual void run() override; + +public: + TextBrowserDownloadThread(TextBrowserDownloadQueue* queue); +}; + +class BINARYNINJAUIAPI TextBrowser: public QTextBrowser +{ + Q_OBJECT + + QSharedPointer<TextBrowserDownloadCache> m_cache; + bool m_ownedCache; + + TextBrowserDownloadQueue* m_queue; + bool m_resizeImagesToWidth = false; + + std::set<QUrl> m_requested; + std::optional<QUrl> m_markdownUrl; + QString m_markdownPrefix; + + void resizeImageFragment(QTextBlock& block, QTextFragment fragment, + QTextImageFormat imgFormat, const QImage& contents); + +protected: + virtual void resizeEvent(QResizeEvent* e) override; + +public: + TextBrowser(QSharedPointer<TextBrowserDownloadCache> cache = QSharedPointer<TextBrowserDownloadCache>()); + virtual ~TextBrowser(); + + void reset(); + virtual QVariant loadResource(int type, const QUrl &name) override; + + void resizeImagesToWidth(); + QSharedPointer<TextBrowserDownloadCache> cache() { return m_cache; } + + void downloadMarkdown(QUrl url, QString prefix = QString()); + +private Q_SLOTS: + void dataDownloaded(QUrl name, QByteArray contents); +}; |
