mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
feat(textstyle): Change markdown syntax to be more intuitive
BREAKING CHANGE: Current markdown syntax is unintuitive, and thus we have agreed on switching to @SkyzohKey's implementation. Replaces all instances of Markdown with Text Styling. Closes #3404.
This commit is contained in:
parent
1bd86f7eee
commit
32e48a979c
|
@ -220,15 +220,15 @@ Videochats and file transfers are currently unsupported in groupchats.
|
||||||
## Message Styling
|
## Message Styling
|
||||||
|
|
||||||
Similar to other messaging applications, qTox supports stylized text formatting.
|
Similar to other messaging applications, qTox supports stylized text formatting.
|
||||||
Formatting follows
|
|
||||||
[Markdown syntax](https://daringfireball.net/projects/markdown/syntax), thus:
|
|
||||||
|
|
||||||
* For **Bold**, surround text in double asterisks or underscores: `**text**`
|
* For **Bold**, surround text in single or double asterisks: `*text*`
|
||||||
or `__text__`
|
or `**text**`
|
||||||
* For **Italics**, surround text in single asterisks or underscores: `*text*`
|
* For **Italics**, surround text in single or double forward slashes: `/text/`
|
||||||
or `_text_`
|
or `//text//`
|
||||||
* For **Strikethrough**, surround text in single tilde's: `~text~`
|
* For **Strikethrough**, surround text in single or double tilde's: `~text~`
|
||||||
* For **Underline**, surround text in single dashes: `-text-`
|
or `~~text~~`
|
||||||
|
* For **Underline**, surround text in single or double underscores: `_text_`
|
||||||
|
or `__text__`
|
||||||
* For **Code**, surround your code in in single backticks: `` `text` ``
|
* For **Code**, surround your code in in single backticks: `` `text` ``
|
||||||
|
|
||||||
Additionally, qTox supports three modes of Markdown parsing:
|
Additionally, qTox supports three modes of Markdown parsing:
|
||||||
|
|
|
@ -55,9 +55,9 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString &sender, const QSt
|
||||||
//quotes (green text)
|
//quotes (green text)
|
||||||
text = detectQuotes(detectAnchors(text), type);
|
text = detectQuotes(detectAnchors(text), type);
|
||||||
|
|
||||||
//markdown
|
//text styling
|
||||||
if (Settings::getInstance().getMarkdownPreference() != NONE)
|
if (Settings::getInstance().getStylePreference() != NONE)
|
||||||
text = detectMarkdown(text);
|
text = detectStyle(text);
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
|
@ -198,19 +198,21 @@ void ChatMessage::hideDate()
|
||||||
c->hide();
|
c->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ChatMessage::detectMarkdown(const QString &str)
|
QString ChatMessage::detectStyle(const QString &str)
|
||||||
{
|
{
|
||||||
QString out = str;
|
QString out = str;
|
||||||
|
|
||||||
// Create regex for certain markdown syntax
|
// Create regex for text styling syntax
|
||||||
QRegExp exp("(\\*\\*)([^\\*\\*]{2,})(\\*\\*)" // Bold **text**
|
QRegExp exp("(\\*)([^\\*]{2,})(\\*)" // Bold *text*
|
||||||
"|(\\*)([^\\*]{2,})(\\*)" // Italics *text*
|
"|(\\*\\*)([^\\*\\*]{2,})(\\*\\*)" // Bold **text**
|
||||||
"|(\\_)([^\\_]{2,})(\\_)" // Italics _text_
|
"|(\\/)([^\\/]{2,})(\\/)" // Italics /text/
|
||||||
"|(\\_\\_)([^\\_\\_]{2,})(\\_\\_)" // Bold __text__
|
"|(\\/\\/)([^\\/\\/]{2,})(\\/\\/)" // Italics //text//
|
||||||
"|(\\-)([^\\-]{2,})(\\-)" // Underline -text-
|
"|(\\_)([^\\_]{2,})(\\_)" // Underline _text_
|
||||||
"|(\\~)([^\\~]{2,})(\\~)" // Strike ~text~
|
"|(\\_\\_)([^\\_\\_]{2,})(\\_\\_)" // Underline __text__
|
||||||
"|(\\~~)([^\\~\\~]{2,})(\\~~)" // Strike ~~text~~
|
"|(\\~)([^\\~]{2,})(\\~)" // Strike ~text~
|
||||||
"|(\\`)([^\\`]{2,})(\\`)" // Codeblock `text`
|
"|(\\~\\~)([^\\~\\~]{2,})(\\~\\~)" // Strike ~~text~~
|
||||||
|
"|(\\`)([^\\`]{2,})(\\`)" // Codeblock `text`
|
||||||
|
"|(\\`\\`\\`)([^\\`\\`\\`]{2,})(\\`\\`\\`)" // Codeblock ```\ntext\n```
|
||||||
);
|
);
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
@ -224,28 +226,32 @@ QString ChatMessage::detectMarkdown(const QString &str)
|
||||||
if ((snipCheck.startsWith(' ') || snipCheck.startsWith('>') || offset == 0)
|
if ((snipCheck.startsWith(' ') || snipCheck.startsWith('>') || offset == 0)
|
||||||
&& ((snipCheck.endsWith(' ') || snipCheck.endsWith('<')) || offset + snippet.length() == out.length()))
|
&& ((snipCheck.endsWith(' ') || snipCheck.endsWith('<')) || offset + snippet.length() == out.length()))
|
||||||
{
|
{
|
||||||
int mul = 0; // Determines how many characters to strip from markdown text
|
int mul = 0; // Determines how many characters to strip from text
|
||||||
// Set mul depending on markdownPreference
|
// Set mul depending on styleownPreference
|
||||||
if (Settings::getInstance().getMarkdownPreference() == WITHOUT_CHARS)
|
if (Settings::getInstance().getStylePreference() == WITHOUT_CHARS)
|
||||||
mul = 2;
|
mul = 2;
|
||||||
|
|
||||||
// Match captured string to corresponding md format
|
// Match captured string to corresponding style format
|
||||||
if (exp.cap(1) == "**") // Bold **text**
|
if (exp.cap(1) == "*" && snippet.length() > 2) // Bold *text*
|
||||||
|
htmledSnippet = QString("<b>%1</b>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
||||||
|
else if (exp.cap(4) == "**" && snippet.length() > 4) // Bold **text**
|
||||||
htmledSnippet = QString("<b>%1</b>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
htmledSnippet = QString("<b>%1</b>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
||||||
else if (exp.cap(4) == "*" && snippet.length() > 2) // Italics *text*
|
else if (exp.cap(7) == "/" && snippet.length() > 2) // Italics /text/
|
||||||
htmledSnippet = QString("<i>%1</i>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
htmledSnippet = QString("<i>%1</i>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
||||||
else if (exp.cap(7) == "_" && snippet.length() > 2) // Italics _text_
|
else if (exp.cap(10) == "//" && snippet.length() > 4) // Italics //text//
|
||||||
htmledSnippet = QString("<i>%1</i>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
htmledSnippet = QString("<i>%1</i>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
||||||
else if (exp.cap(10) == "__"&& snippet.length() > 4) // Bold __text__
|
else if (exp.cap(13) == "_"&& snippet.length() > 2) // Underline _text_
|
||||||
htmledSnippet = QString("<b>%1</b>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
|
||||||
else if (exp.cap(13) == "-" && snippet.length() > 2) // Underline -text-
|
|
||||||
htmledSnippet = QString("<u>%1</u>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
htmledSnippet = QString("<u>%1</u>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
||||||
else if (exp.cap(16) == "~" && snippet.length() > 2) // Strikethrough ~text~
|
else if (exp.cap(16) == "__" && snippet.length() > 4) // Underline __text__
|
||||||
|
htmledSnippet = QString("<u>%1</u>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
||||||
|
else if (exp.cap(19) == "~" && snippet.length() > 2) // Strike ~text~
|
||||||
htmledSnippet = QString("<s>%1</s>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
htmledSnippet = QString("<s>%1</s>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
||||||
else if (exp.cap(19) == "~~" && snippet.length() > 4) // Strikethrough ~~text~~
|
else if (exp.cap(22) == "~~" && snippet.length() > 4) // Strike ~~text~~
|
||||||
htmledSnippet = QString("<s>%1</s>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
htmledSnippet = QString("<s>%1</s>").arg(snippet.mid(mul,snippet.length()-2*mul));
|
||||||
else if (exp.cap(22) == "`" && snippet.length() > 2) // Codeblock `text`
|
else if (exp.cap(25) == "`" && snippet.length() > 2) // Codeblock `text`
|
||||||
htmledSnippet = QString("<font color=#595959><code>%1</code></font>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
htmledSnippet = QString("<font color=#595959><code>%1</code></font>").arg(snippet.mid(mul/2,snippet.length()-mul));
|
||||||
|
else if (exp.cap(28) == "```" && snippet.length() > 6) // Codeblock ```text```
|
||||||
|
htmledSnippet = QString("<font color=#595959><code>%1</code></font>").arg(snippet.mid(4*mul,snippet.length()-8*mul));
|
||||||
else
|
else
|
||||||
htmledSnippet = snippet;
|
htmledSnippet = snippet;
|
||||||
out.replace(offset, exp.cap().length(), htmledSnippet);
|
out.replace(offset, exp.cap().length(), htmledSnippet);
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
void hideDate();
|
void hideDate();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static QString detectMarkdown(const QString& str);
|
static QString detectStyle(const QString& str);
|
||||||
static QString detectAnchors(const QString& str);
|
static QString detectAnchors(const QString& str);
|
||||||
static QString detectQuotes(const QString& str, MessageType type);
|
static QString detectQuotes(const QString& str, MessageType type);
|
||||||
static QString wrapDiv(const QString& str, const QString& div);
|
static QString wrapDiv(const QString& str, const QString& div);
|
||||||
|
|
|
@ -182,7 +182,7 @@ void Settings::loadGlobal()
|
||||||
separateWindow = s.value("separateWindow", false).toBool();
|
separateWindow = s.value("separateWindow", false).toBool();
|
||||||
dontGroupWindows = s.value("dontGroupWindows", true).toBool();
|
dontGroupWindows = s.value("dontGroupWindows", true).toBool();
|
||||||
groupchatPosition = s.value("groupchatPosition", true).toBool();
|
groupchatPosition = s.value("groupchatPosition", true).toBool();
|
||||||
markdownPreference = static_cast<MarkdownType>(s.value("markdownPreference", 1).toInt());
|
stylePreference = static_cast<StyleType>(s.value("stylePreference", 1).toInt());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup("Advanced");
|
s.beginGroup("Advanced");
|
||||||
|
@ -434,7 +434,7 @@ void Settings::saveGlobal()
|
||||||
s.setValue("groupchatPosition", groupchatPosition);
|
s.setValue("groupchatPosition", groupchatPosition);
|
||||||
s.setValue("autoSaveEnabled", autoSaveEnabled);
|
s.setValue("autoSaveEnabled", autoSaveEnabled);
|
||||||
s.setValue("globalAutoAcceptDir", globalAutoAcceptDir);
|
s.setValue("globalAutoAcceptDir", globalAutoAcceptDir);
|
||||||
s.setValue("markdownPreference", static_cast<int>(markdownPreference));
|
s.setValue("stylePreference", static_cast<int>(stylePreference));
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup("Advanced");
|
s.beginGroup("Advanced");
|
||||||
|
@ -1249,16 +1249,16 @@ void Settings::setDateFormat(const QString &format)
|
||||||
dateFormat = format;
|
dateFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkdownType Settings::getMarkdownPreference() const
|
StyleType Settings::getStylePreference() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker{&bigLock};
|
QMutexLocker locker{&bigLock};
|
||||||
return markdownPreference;
|
return stylePreference;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setMarkdownPreference(MarkdownType newValue)
|
void Settings::setStylePreference(StyleType newValue)
|
||||||
{
|
{
|
||||||
QMutexLocker locker{&bigLock};
|
QMutexLocker locker{&bigLock};
|
||||||
markdownPreference = newValue;
|
stylePreference = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Settings::getWindowGeometry() const
|
QByteArray Settings::getWindowGeometry() const
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Db { enum class syncType; }
|
||||||
|
|
||||||
enum ProxyType {ptNone, ptSOCKS5, ptHTTP};
|
enum ProxyType {ptNone, ptSOCKS5, ptHTTP};
|
||||||
|
|
||||||
enum MarkdownType {NONE, WITH_CHARS, WITHOUT_CHARS};
|
enum StyleType {NONE, WITH_CHARS, WITHOUT_CHARS};
|
||||||
|
|
||||||
class Settings : public QObject
|
class Settings : public QObject
|
||||||
{
|
{
|
||||||
|
@ -212,8 +212,8 @@ public:
|
||||||
int getThemeColor() const;
|
int getThemeColor() const;
|
||||||
void setThemeColor(const int& value);
|
void setThemeColor(const int& value);
|
||||||
|
|
||||||
MarkdownType getMarkdownPreference() const;
|
StyleType getStylePreference() const;
|
||||||
void setMarkdownPreference(MarkdownType newValue);
|
void setStylePreference(StyleType newValue);
|
||||||
|
|
||||||
bool isCurstomEmojiFont() const;
|
bool isCurstomEmojiFont() const;
|
||||||
void setCurstomEmojiFont(bool value);
|
void setCurstomEmojiFont(bool value);
|
||||||
|
@ -426,7 +426,7 @@ private:
|
||||||
|
|
||||||
// ChatView
|
// ChatView
|
||||||
QFont chatMessageFont;
|
QFont chatMessageFont;
|
||||||
MarkdownType markdownPreference;
|
StyleType stylePreference;
|
||||||
int firstColumnHandlePos;
|
int firstColumnHandlePos;
|
||||||
int secondColumnHandlePosFromRight;
|
int secondColumnHandlePosFromRight;
|
||||||
QString timestampFormat;
|
QString timestampFormat;
|
||||||
|
|
|
@ -124,7 +124,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
||||||
const QFont chatBaseFont = s.getChatMessageFont();
|
const QFont chatBaseFont = s.getChatMessageFont();
|
||||||
bodyUI->txtChatFontSize->setValue(QFontInfo(chatBaseFont).pixelSize());
|
bodyUI->txtChatFontSize->setValue(QFontInfo(chatBaseFont).pixelSize());
|
||||||
bodyUI->txtChatFont->setCurrentFont(chatBaseFont);
|
bodyUI->txtChatFont->setCurrentFont(chatBaseFont);
|
||||||
bodyUI->markdownComboBox->setCurrentIndex(s.getMarkdownPreference());
|
bodyUI->textStyleComboBox->setCurrentIndex(s.getStylePreference());
|
||||||
bodyUI->cbAutorun->setChecked(s.getAutorun());
|
bodyUI->cbAutorun->setChecked(s.getAutorun());
|
||||||
|
|
||||||
bool showSystemTray = s.getShowSystemTray();
|
bool showSystemTray = s.getShowSystemTray();
|
||||||
|
@ -233,7 +233,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
||||||
connect(bodyUI->showInFront, &QCheckBox::stateChanged, this, &GeneralForm::onSetShowInFront);
|
connect(bodyUI->showInFront, &QCheckBox::stateChanged, this, &GeneralForm::onSetShowInFront);
|
||||||
connect(bodyUI->notifySound, &QCheckBox::stateChanged, this, &GeneralForm::onSetNotifySound);
|
connect(bodyUI->notifySound, &QCheckBox::stateChanged, this, &GeneralForm::onSetNotifySound);
|
||||||
connect(bodyUI->busySound, &QCheckBox::stateChanged, this, &GeneralForm::onSetBusySound);
|
connect(bodyUI->busySound, &QCheckBox::stateChanged, this, &GeneralForm::onSetBusySound);
|
||||||
connect(bodyUI->markdownComboBox, &QComboBox::currentTextChanged, this, &GeneralForm::onMarkdownUpdated);
|
connect(bodyUI->textStyleComboBox, &QComboBox::currentTextChanged, this, &GeneralForm::onStyleUpdated);
|
||||||
connect(bodyUI->groupAlwaysNotify, &QCheckBox::stateChanged, this, &GeneralForm::onSetGroupAlwaysNotify);
|
connect(bodyUI->groupAlwaysNotify, &QCheckBox::stateChanged, this, &GeneralForm::onSetGroupAlwaysNotify);
|
||||||
connect(bodyUI->autoacceptFiles, &QCheckBox::stateChanged, this, &GeneralForm::onAutoAcceptFileChange);
|
connect(bodyUI->autoacceptFiles, &QCheckBox::stateChanged, this, &GeneralForm::onAutoAcceptFileChange);
|
||||||
connect(bodyUI->autoSaveFilesDir, SIGNAL(clicked()), this, SLOT(onAutoSaveDirChange()));
|
connect(bodyUI->autoSaveFilesDir, SIGNAL(clicked()), this, SLOT(onAutoSaveDirChange()));
|
||||||
|
@ -396,9 +396,9 @@ void GeneralForm::onUseEmoticonsChange()
|
||||||
bodyUI->smileyPackBrowser->setEnabled(bodyUI->useEmoticons->isChecked());
|
bodyUI->smileyPackBrowser->setEnabled(bodyUI->useEmoticons->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralForm::onMarkdownUpdated()
|
void GeneralForm::onStyleUpdated()
|
||||||
{
|
{
|
||||||
Settings::getInstance().setMarkdownPreference(static_cast<MarkdownType>(bodyUI->markdownComboBox->currentIndex()));
|
Settings::getInstance().setStylePreference(static_cast<StyleType>(bodyUI->textStyleComboBox->currentIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralForm::onSetStatusChange()
|
void GeneralForm::onSetStatusChange()
|
||||||
|
|
|
@ -53,7 +53,7 @@ private slots:
|
||||||
void onStyleSelected(QString style);
|
void onStyleSelected(QString style);
|
||||||
void onTimestampSelected(int index);
|
void onTimestampSelected(int index);
|
||||||
void onDateFormatSelected(int index);
|
void onDateFormatSelected(int index);
|
||||||
void onMarkdownUpdated();
|
void onStyleUpdated();
|
||||||
void onSetStatusChange();
|
void onSetStatusChange();
|
||||||
void onAutoAwayChanged();
|
void onAutoAwayChanged();
|
||||||
void onUseEmoticonsChange();
|
void onUseEmoticonsChange();
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1270</width>
|
<width>1278</width>
|
||||||
<height>1468</height>
|
<height>1382</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,0,1">
|
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,0,1">
|
||||||
|
@ -336,12 +336,12 @@ instead of closing itself.</string>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="transLabel_2">
|
<widget class="QLabel" name="textStyleLabel">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>New Markdown preference may not load until qTox restarts.</string>
|
<string>New text styling preference may not load until qTox restarts.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Markdown format:</string>
|
<string>Text Style format:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
@ -375,7 +375,7 @@ instead of closing itself.</string>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" colspan="2">
|
<item row="1" column="1" colspan="2">
|
||||||
<widget class="QComboBox" name="markdownComboBox">
|
<widget class="QComboBox" name="textStyleComboBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -383,7 +383,10 @@ instead of closing itself.</string>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select Markdown preference.</string>
|
<string>Select text styling preference.</string>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
Loading…
Reference in New Issue
Block a user