This commit is contained in:
defnax 2026-08-31 12:00:43 -07:00 committed by GitHub
commit bf77eef30f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 337 additions and 18 deletions

View File

@ -35,6 +35,7 @@
#include "util/qtthreadsutils.h"
#include "util/HandleRichText.h"
#include "gui/Identity/IdDialog.h"
#include "gui/settings/rsharesettings.h"
#include "gui/MainWindow.h"
#include "util/DateTime.h"
#include <QMovie>
@ -236,8 +237,10 @@ void BoardPostDisplayWidgetBase::baseSetup()
if (urlOkay)
{
QString siteurl = url.toEncoded();
linkColor = Settings->getLinkColor();
label->setStyleSheet("text-decoration: underline; color:#2255AA;");
QString colorstring = QString("%1;").arg(linkColor.name());
label->setStyleSheet("text-decoration: underline; color:" + colorstring );
label->setCursor(QCursor(Qt::PointingHandCursor));
label->setToolTip(siteurl);

View File

@ -109,6 +109,8 @@ signals:
protected:
RsPostedPost mPost;
uint8_t mDisplayFlags;
private:
QColor linkColor;
};
class BoardPostDisplayWidget_compact : public BoardPostDisplayWidgetBase
@ -151,6 +153,8 @@ protected:
void setup() override; // to be overloaded by the different views
private:
QColor linkColor;
/** Qt Designer generated object */
Ui::BoardPostDisplayWidget_compact *ui;
};

View File

@ -230,9 +230,14 @@ void PostedCardView::fill()
if (urlOkay)
{
linkColor = Settings->getLinkColor();
QString colorstring = QString("%1;").arg(linkColor.name());
QString urlstr = QString("<a href=\"");
urlstr += QString(url.toEncoded());
urlstr += QString("\" ><span style=\" text-decoration: underline; color:#2255AA;\"> ");
urlstr += QString("\" ><span style=\" text-decoration: underline; color:");
urlstr += colorstring;
urlstr += QString("\"> ");
urlstr += messageName();
urlstr += QString(" </span></a>");

View File

@ -57,6 +57,8 @@ protected:
void toggleNotes() override;
private:
QColor linkColor;
/** Qt Designer generated object */
Ui::PostedCardView *ui;
};

View File

@ -33,6 +33,7 @@
#include "util/misc.h"
#include "util/qtthreadsutils.h"
#include "util/RichTextEdit.h"
#include "util/HandleRichText.h"
#include "gui/feeds/SubFileItem.h"
#include "util/rsdir.h"
@ -167,6 +168,7 @@ void PostedCreatePostDialog::createPost()
if(!ui->RichTextEditWidget->toPlainText().trimmed().isEmpty()) {
QString text;
text = ui->RichTextEditWidget->toHtml();
RsHtml::optimizeHtml(text);
post.mNotes = std::string(text.toUtf8());
}

View File

@ -920,7 +920,7 @@ void PostedListWidgetWithModel::insertBoardDetails(const RsPostedGroup& group)
ui->infoAdministrator->setId(group.mMeta.mAuthorId) ;
link = RetroShareLink::createMessage(group.mMeta.mAuthorId, "");
ui->infoAdministrator->setText(link.toHtml());
ui->infoAdministrator->setText(link.toHtmlColored());
ui->createdinfolabel->setText(DateTime::formatDateTime(group.mMeta.mPublishTs));

View File

@ -46,7 +46,7 @@
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QTextBrowser" name="trans_Description">
<widget class="RSTextBrowser" name="trans_Description">
<property name="styleSheet">
<string notr="true"/>
</property>
@ -619,6 +619,11 @@ p, li { white-space: pre-wrap; }
<header>gui/common/RSTabWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>RSTextBrowser</class>
<extends>QTextBrowser</extends>
<header>gui/common/RSTextBrowser.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../icons.qrc"/>

View File

@ -40,6 +40,7 @@
#include "msgs/MessageComposer.h"
#include "Posted/PostedDialog.h"
#include "util/misc.h"
#include "gui/settings/rsharesettings.h"
#include <retroshare/rsfiles.h>
#include <retroshare/rsgxsforums.h>
@ -1218,13 +1219,32 @@ QString RetroShareLink::niceName() const
QString RetroShareLink::toHtml() const
{
QColor linkColor = Settings->getLinkColor();
QString colorstring = QString("%1;").arg(linkColor.name());
QString html = "<a href=\"" + toString() + "\"";
QString linkTitle = title();
if (!linkTitle.isEmpty()) {
html += " title=\"" + linkTitle + "\"";
}
html += ">" + niceName() + "</a>" ;
html += " style=\"color:" + colorstring + "\">" + niceName() + "</a>" ;
return html;
}
QString RetroShareLink::toHtmlColored() const
{
QColor linkColor = Settings->getLinkColor();
QString colorstring = QString("%1;").arg(linkColor.name());
QString html = "<a href=\"" + toString() + "\"";
QString linkTitle = title();
if (!linkTitle.isEmpty()) {
html += " title=\"" + linkTitle + "\"";
}
html += " style=\"color:" + colorstring + "\">" + niceName() + "</a>" ;
return html;
}

View File

@ -42,6 +42,7 @@
#include <QString>
#include <QUrl>
#include <QVector>
#include <QColor>
#include <stdint.h>
@ -142,6 +143,8 @@ class RetroShareLink
QString toHtmlSize() const ;
QString toHtmlColored() const;
QUrl toUrl() const ;
bool operator==(const RetroShareLink& l) const { return _type == l._type && _hash == l._hash ; }
@ -180,6 +183,7 @@ class RetroShareLink
time_t _time_stamp ; // time stamp at which the link will expire.
QString _radix_group_data;
uint32_t _count ;
QColor linkColor;
unsigned int _subType; // for general use as sub type for _type (RSLINK_SUBTYPE_...)
};

View File

@ -30,6 +30,7 @@
#include <QMenu>
#include "MimeTextEdit.h"
#include "gui/settings/rsharesettings.h"
#include "util/HandleRichText.h"
#include "gui/RetroShareLink.h"
#include "util/imageutil.h"
@ -329,3 +330,42 @@ void MimeTextEdit::copyImage()
QTextCursor cursor = cursorForPosition(point);
ImageUtil::copyImage(window(), cursor);
}
void MimeTextEdit::updateLinkColor()
{
linkColor = Settings->getLinkColor();
QPalette p = palette();
p.setColor(QPalette::Link, linkColor);
p.setColor(QPalette::LinkVisited, linkColor);
setPalette(p);
if (document()) {
document()->setDefaultStyleSheet(QString("a[href] { color: %1; }").arg(linkColor.name()));
}
}
QString MimeTextEdit::toHtml(const QByteArray &encoding) const
{
QTextDocument *doc = document();
QString oldSheet;
if (doc) {
oldSheet = doc->defaultStyleSheet();
doc->setDefaultStyleSheet("");
}
QString html;
if (encoding.isEmpty()) {
html = QTextEdit::toHtml();
} else {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Qt 6: toHtml() takes no arguments
html = doc->toHtml();
#else
// Qt 5: toHtml() accepts encoding parameter
html = doc->toHtml(encoding);
#endif
}
if (doc) {
doc->setDefaultStyleSheet(oldSheet);
}
return html;
}

View File

@ -52,12 +52,15 @@ public:
QVariant textColorQuotes() const { return highliter->textColorQuotes();}
bool onlyPlainText() const {return mOnlyPlainText;}
QString toHtml(const QByteArray &encoding = QByteArray()) const;
void setMaxBytes(int limit) {mMaxBytes = limit;}
public slots:
void setTextColorQuote(QColor textColorQuote) { highliter->setTextColorQuote(textColorQuote);}
void setTextColorQuotes(QVariant textColorQuotes) { highliter->setTextColorQuotes(textColorQuotes);}
void setOnlyPlainText(bool bOnlyPlainText) {mOnlyPlainText = bOnlyPlainText;}
void updateLinkColor();
signals:
void calculateContextMenuActions();
@ -91,6 +94,7 @@ private:
RsSyntaxHighlighter *highliter;
bool mOnlyPlainText;
int mMaxBytes = -1; //limit content size, for pasting images
QColor linkColor;
};
#endif // MIMETEXTEDIT_H

View File

@ -19,6 +19,7 @@
*******************************************************************************/
#include "RSTextBrowser.h"
#include "gui/settings/rsharesettings.h"
#include "RSImageBlockWidget.h"
#include "gui/common/FilesDefs.h"
@ -360,3 +361,53 @@ void RSTextBrowser::copyImage()
QTextCursor cursor = cursorForPosition(point);
ImageUtil::copyImage(window(), cursor);
}
void RSTextBrowser::showEvent(QShowEvent *event)
{
if (!event->spontaneous()) {
updateLinkColor();
}
}
void RSTextBrowser::updateLinkColor()
{
linkColor = Settings->getLinkColor();
QPalette p = palette();
p.setColor(QPalette::Link, linkColor);
p.setColor(QPalette::LinkVisited, linkColor);
setPalette(p);
if (document()) {
document()->setDefaultStyleSheet(QString("a[href] { color: %1; }").arg(linkColor.name()));
if (!document()->isEmpty()) {
QString html = document()->toHtml();
document()->setHtml(html);
}
}
}
QString RSTextBrowser::toHtml(const QByteArray &encoding) const
{
QTextDocument *doc = document();
QString oldSheet;
if (doc) {
oldSheet = doc->defaultStyleSheet();
doc->setDefaultStyleSheet("");
}
QString html;
if (encoding.isEmpty()) {
html = QTextBrowser::toHtml();
} else {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// Qt 6: toHtml() takes no arguments
html = doc->toHtml();
#else
// Qt 5: toHtml() accepts encoding parameter
html = doc->toHtml(encoding);
#endif
}
if (doc) {
doc->setDefaultStyleSheet(oldSheet);
}
return html;
}

View File

@ -58,6 +58,8 @@ public:
QVariant textColorQuotes() const { return highlighter->textColorQuotes();}
bool getShowImages() const { return mShowImages; }
QString toHtml(const QByteArray &encoding = QByteArray()) const;
QMenu *createStandardContextMenuFromPoint(const QPoint &widgetPos);
Q_SIGNALS:
@ -67,6 +69,7 @@ public slots:
void showImages();
void setTextColorQuote(QColor textColorQuote) { highlighter->setTextColorQuote(textColorQuote);}
void setTextColorQuotes(QVariant textColorQuotes) { highlighter->setTextColorQuotes(textColorQuotes);}
void updateLinkColor();
private slots:
void linkClicked(const QUrl &url);
@ -77,6 +80,7 @@ private slots:
protected:
void paintEvent(QPaintEvent *event);
void showEvent(QShowEvent *event);
virtual void contextMenuEvent(QContextMenuEvent *event);
private:
@ -90,6 +94,7 @@ private:
bool mLinkClickActive;
RsSyntaxHighlighter *highlighter;
QList<QAction*> mContextMenuActions;
QColor linkColor;
#ifdef RSTEXTBROWSER_CHECKIMAGE_DEBUG
QRect mCursorRectStart;
QRect mCursorRectLeft;

View File

@ -729,6 +729,7 @@ void CreateGxsChannelMsg::sendMsg()
QString text;
text = RichTextEditWidget->toHtml();
RsHtml::optimizeHtml(text);
std::string msg = std::string(text.toUtf8());
std::list<RsGxsFile> files;

View File

@ -1440,7 +1440,7 @@ void GxsChannelPostsWidgetWithModel::insertChannelDetails(const RsGxsChannelGrou
if(!group.mMeta.mAuthorId.isNull())
{
RetroShareLink link = RetroShareLink::createMessage(group.mMeta.mAuthorId, "");
ui->infoAdministrator->setText(link.toHtml());
ui->infoAdministrator->setText(link.toHtmlColored());
}
else
ui->infoAdministrator->setText("[No contact author]");

View File

@ -397,7 +397,7 @@
</layout>
</item>
<item>
<widget class="QTextBrowser" name="infoDescription">
<widget class="RSTextBrowser" name="infoDescription">
<property name="html">
<string notr="true">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
@ -548,7 +548,7 @@ p, li { white-space: pre-wrap; }
</widget>
</item>
<item>
<widget class="QTextBrowser" name="postDetails_TE">
<widget class="RSTextBrowser" name="postDetails_TE">
<property name="openExternalLinks">
<bool>true</bool>
</property>
@ -685,6 +685,11 @@ p, li { white-space: pre-wrap; }
<header>gui/gxs/GxsCommentDialog.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>RSTextBrowser</class>
<extends>QTextBrowser</extends>
<header>gui/common/RSTextBrowser.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../icons.qrc"/>

View File

@ -2422,10 +2422,10 @@ bool MessageComposer::fileSave()
QTextStream ts(&file);
#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0)
ts.setEncoding(QStringConverter::Utf8);
ts << ui.msgText->document()->toHtml();
ts << ui.msgText->toHtml();
#else
ts.setCodec(QTextCodec::codecForName("UTF-8"));
ts << ui.msgText->document()->toHtml("UTF-8");
ts << ui.msgText->toHtml("UTF-8");
#endif
std::cerr << "Setting modified 002 = false" << std::endl;
ui.msgText->document()->setModified(false);

View File

@ -707,7 +707,7 @@ void MessageWidget::fill(const std::string &msgId)
}
else
{
ui.fromText->setText(link.toHtml());
ui.fromText->setText(link.toHtmlColored());
ui.fromText->setToolTip(tooltip_string) ;
if (toolButtonReply) toolButtonReply->setEnabled(true);
}
@ -807,10 +807,10 @@ void MessageWidget::saveAs()
QTextStream ts(&file);
#if QT_VERSION >= QT_VERSION_CHECK (6, 0, 0)
ts.setEncoding(QStringConverter::Utf8);
ts << ui.msgText->document()->toHtml();
ts << ui.msgText->toHtml();
#else
ts.setCodec(QTextCodec::codecForName("UTF-8"));
ts << ui.msgText->document()->toHtml("UTF-8");
ts << ui.msgText->toHtml("UTF-8");
#endif
ui.msgText->document()->setModified(false);
}

View File

@ -40,6 +40,7 @@
#include "util/DateTime.h"
#include <QAbstractItemView>
#include <QColorDialog>
#include <QComboBox>
#include <QCheckBox>
#include <QDir>
@ -398,6 +399,11 @@ void AppearancePage::load()
whileBlocking(ui.checkBoxShowSystrayOnStatus)->setChecked(Settings->valueFromGroup("StatusBar", "ShowSysTrayOnStatusBar", QVariant(false)).toBool());
whileBlocking(ui.minimumFontSize_SB)->setValue(Settings->getFontSize());
rgbLinkColor=Settings->getLinkColor();
QPixmap colorpix(24, 24);
colorpix.fill(rgbLinkColor);
ui.linkColorButton->setIcon(colorpix);
}
void AppearancePage::updateFontSize()
@ -415,3 +421,25 @@ void AppearancePage::updateDateFormat()
RsGUIEventManager::getInstance()->notifySettingsChanged();
}
void AppearancePage::on_linkColorButton_clicked()
{
QColor color = QColorDialog::getColor(QColor::fromRgba(rgbLinkColor), window(), "", QColorDialog::ShowAlphaChannel);
if (color.isValid()) {
rgbLinkColor = color.rgba();
QPixmap pix(24, 24);
pix.fill(color);
ui.linkColorButton->setIcon(pix);
Settings->setLinkColor(rgbLinkColor);
}
}
void AppearancePage::on_resetButton_clicked()
{
QRgb color = QString::number(QColor(118, 118, 255).rgba()).toUInt();
defaultColor = color;
rgbLinkColor = color;
QPixmap pix(24, 24);
pix.fill(color);
ui.linkColorButton->setIcon(pix);
Settings->setLinkColor(defaultColor);
}

View File

@ -74,9 +74,15 @@ private slots:
void updateStyle() ;
void updateFontSize();
void on_linkColorButton_clicked();
void on_resetButton_clicked();
private:
void switch_status(MainWindow::StatusElement s,const QString& key,bool b);
QRgb rgbLinkColor;
QRgb defaultColor;
/** Qt Designer generated object */
Ui::AppearancePage ui;
};

View File

@ -109,7 +109,7 @@
</widget>
</item>
<item row="3" column="0">
<item row="3" column="0" rowspan="2">
<widget class="QGroupBox" name="grpToolBar">
<property name="minimumSize">
<size>
@ -336,7 +336,62 @@
</layout>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="4" column="1">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Link Color</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item>
<widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Color of the links</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="linkColorButton">
<property name="minimumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Set link color</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="resetButton">
<property name="toolTip">
<string>Reset to default color</string>
</property>
<property name="icon">
<iconset resource="../icons.qrc">
<normaloff>:/icons/textedit/undo.png</normaloff>:/icons/textedit/undo.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QGroupBox" name="grpStatus">
<property name="title">
<string>Status Bar</string>
@ -445,7 +500,7 @@
</layout>
</widget>
</item>
<item row="5" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<spacer name="AppearancePageVSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -552,6 +607,8 @@
<header>gui/common/RSComboBox.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="../icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1243,6 +1243,15 @@ void RshareSettings::setMessageFontSize(int value)
setValueToGroup("Message", "FontSize", value);
}
void RshareSettings::setLinkColor(QRgb rgbValue)
{
setValueToGroup("Chat", "LinkColor", QString::number(rgbValue));
}
QRgb RshareSettings::getLinkColor()
{
return valueFromGroup("Chat", "LinkColor", QString::number(QColor(118, 118, 255).rgba())).toUInt();
}
#ifdef RS_JSONAPI
bool RshareSettings::getJsonApiEnabled()
{

View File

@ -393,6 +393,9 @@ public:
int getMessageFontSize();
void setMessageFontSize(int value);
void setLinkColor(QRgb rgbValue);
QRgb getLinkColor();
#ifdef RS_JSONAPI
bool getJsonApiEnabled();
void setJsonApiEnabled(bool enabled);

View File

@ -30,6 +30,8 @@
#include <QRegExp>
#include "HandleRichText.h"
#include "gui/common/MimeTextEdit.h"
#include "gui/settings/rsharesettings.h"
#include "gui/RetroShareLink.h"
#include "util/ObjectPainter.h"
#include "util/imageutil.h"
@ -407,7 +409,8 @@ void RsHtml::embedHtml(QTextDocument *textDocument, QDomDocument& doc, QDomEleme
// skip it
} else if (element.tagName().toLower() == "a") {
// skip it
if (embedInfos.myType == Ahref) {
if (embedInfos.myType == Ahref && element.hasAttribute("href")) {
element.setAttribute("style", QString("color: %1;").arg(QColor(Settings->getLinkColor()).name()));
// but add title if not available
if (element.attribute("title").isEmpty()) {
RetroShareLink link(element.attribute("href"));
@ -476,6 +479,7 @@ void RsHtml::embedHtml(QTextDocument *textDocument, QDomDocument& doc, QDomEleme
{
insertedTag = doc.createElement("a");
insertedTag.setAttribute("href", myRE.cap(0));
insertedTag.setAttribute("style", QString("color: %1;").arg(QColor(Settings->getLinkColor()).name()));
insertedTag.appendChild(doc.createTextNode(myRE.cap(0)));
RetroShareLink link(myRE.cap(0));
@ -815,6 +819,66 @@ static void findBestColor(QString &val, qreal bglum, qreal desiredContrast)
#endif // QT_VERSION < 0x040600
}
static void stripLinkColorStyle(QDomElement element)
{
if (element.hasAttribute("style")) {
QString style = element.attribute("style");
style.remove(QRegularExpression("color\\s*:\\s*[^;]+;?", QRegularExpression::CaseInsensitiveOption));
if (style.trimmed().isEmpty()) {
element.removeAttribute("style");
} else {
element.setAttribute("style", style);
}
}
if (element.tagName().toLower() == "font" && element.hasAttribute("color")) {
element.removeAttribute("color");
}
QDomNodeList children = element.childNodes();
for (int i = 0; i < children.length(); ++i) {
QDomNode node = children.item(i);
if (node.isElement()) {
stripLinkColorStyle(node.toElement());
}
}
}
static void stripThemeColors(QDomElement element, const QString &hexColor)
{
if (element.hasAttribute("style")) {
QString style = element.attribute("style");
QRegularExpression re(QString("color\\s*:\\s*%1;?").arg(hexColor), QRegularExpression::CaseInsensitiveOption);
style.remove(re);
if (style.trimmed().isEmpty()) {
element.removeAttribute("style");
} else {
element.setAttribute("style", style);
}
}
if (element.tagName().toLower() == "font" && element.hasAttribute("color")) {
if (element.attribute("color").compare(hexColor, Qt::CaseInsensitive) == 0) {
element.removeAttribute("color");
}
}
if (element.tagName().toLower() == "a") {
stripLinkColorStyle(element);
}
QDomNodeList children = element.childNodes();
for (int i = 0; i < children.length(); ++i) {
QDomNode node = children.item(i);
if (node.isElement()) {
stripThemeColors(node.toElement(), hexColor);
}
}
}
static void stripAllLinkColors(QDomElement element)
{
QColor linkColor = Settings->getLinkColor();
QString hexColor = linkColor.name();
stripThemeColors(element, hexColor);
}
/**
* @brief optimizeHtml: Optimize HTML Text in DomDocument to reduce size
* @param doc: QDomDocument containing Text to optimize
@ -1186,6 +1250,7 @@ void RsHtml::optimizeHtml(QString &text, unsigned int flag /*= 0*/
}
QDomElement body = doc.documentElement();
stripAllLinkColors(body);
QHash<QString, QStringList> stylesList;
QHash<QString, QString> knownStyle;