From 2cb36d8f7ba30e1ba2b4e3566aede9016e15399f Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 12 Mar 2021 03:22:01 -0500 Subject: Add a QTextBrowser capable of showing remote images --- ui/textbrowser.h | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 ui/textbrowser.h 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "binaryninjaapi.h" +#include "uitypes.h" + +class TextBrowser; +class TextBrowserDownloadThread; + +class BINARYNINJAUIAPI TextBrowserDownloadCache +{ + QMutex m_mutex; + std::map m_downloadCache; + std::set 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 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 m_provider; + BinaryNinja::Ref m_downloadInstance; + +protected: + virtual void run() override; + +public: + TextBrowserDownloadThread(TextBrowserDownloadQueue* queue); +}; + +class BINARYNINJAUIAPI TextBrowser: public QTextBrowser +{ + Q_OBJECT + + QSharedPointer m_cache; + bool m_ownedCache; + + TextBrowserDownloadQueue* m_queue; + bool m_resizeImagesToWidth = false; + + std::set m_requested; + std::optional 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 cache = QSharedPointer()); + virtual ~TextBrowser(); + + void reset(); + virtual QVariant loadResource(int type, const QUrl &name) override; + + void resizeImagesToWidth(); + QSharedPointer cache() { return m_cache; } + + void downloadMarkdown(QUrl url, QString prefix = QString()); + +private Q_SLOTS: + void dataDownloaded(QUrl name, QByteArray contents); +}; -- cgit v1.3.1