From de6ee9a2a3389ebf62f181b12632e58d2ffb8879 Mon Sep 17 00:00:00 2001 From: Alex McGrath Date: Thu, 1 Aug 2019 17:07:46 +0100 Subject: [PATCH] Add button and bindings for striking through text This includes icons and a small regex fix from @digitalcircuit --- .../actions/16/format-text-strikethrough.svg | 13 ++++++ .../actions/22/format-text-strikethrough.svg | 14 ++++++ .../actions/24/format-text-strikethrough.svg | 13 ++++++ .../actions/16/format-text-strikethrough.svg | 13 ++++++ .../actions/22/format-text-strikethrough.svg | 14 ++++++ .../actions/24/format-text-strikethrough.svg | 13 ++++++ .../actions/format-text-strikethrough.png | Bin 0 -> 441 bytes .../actions/format-text-strikethrough.png | Bin 0 -> 579 bytes .../actions/format-text-strikethrough.png | Bin 0 -> 1359 bytes .../actions/format-text-strikethrough.png | Bin 0 -> 1107 bytes data/stylesheets/m4yer.qss | 2 + src/qtui/inputwidget.cpp | 24 ++++++++++ src/qtui/inputwidget.h | 15 ++++++ src/qtui/inputwidget.ui | 43 ++++++++++++++++++ src/qtui/mainwin.cpp | 18 +++++++- src/qtui/mainwin.h | 7 +++ src/uisupport/multilineedit.cpp | 27 +++++++++-- 17 files changed, 212 insertions(+), 4 deletions(-) create mode 100644 3rdparty/icons/breeze-dark/actions/16/format-text-strikethrough.svg create mode 100644 3rdparty/icons/breeze-dark/actions/22/format-text-strikethrough.svg create mode 100644 3rdparty/icons/breeze-dark/actions/24/format-text-strikethrough.svg create mode 100644 3rdparty/icons/breeze/actions/16/format-text-strikethrough.svg create mode 100644 3rdparty/icons/breeze/actions/22/format-text-strikethrough.svg create mode 100644 3rdparty/icons/breeze/actions/24/format-text-strikethrough.svg create mode 100644 3rdparty/icons/oxygen/16x16/actions/format-text-strikethrough.png create mode 100644 3rdparty/icons/oxygen/22x22/actions/format-text-strikethrough.png create mode 100644 3rdparty/icons/oxygen/32x32/actions/format-text-strikethrough.png create mode 100644 3rdparty/icons/oxygen/48x48/actions/format-text-strikethrough.png diff --git a/3rdparty/icons/breeze-dark/actions/16/format-text-strikethrough.svg b/3rdparty/icons/breeze-dark/actions/16/format-text-strikethrough.svg new file mode 100644 index 00000000..e5f4aab2 --- /dev/null +++ b/3rdparty/icons/breeze-dark/actions/16/format-text-strikethrough.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/3rdparty/icons/breeze-dark/actions/22/format-text-strikethrough.svg b/3rdparty/icons/breeze-dark/actions/22/format-text-strikethrough.svg new file mode 100644 index 00000000..24903dd7 --- /dev/null +++ b/3rdparty/icons/breeze-dark/actions/22/format-text-strikethrough.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/3rdparty/icons/breeze-dark/actions/24/format-text-strikethrough.svg b/3rdparty/icons/breeze-dark/actions/24/format-text-strikethrough.svg new file mode 100644 index 00000000..865f4019 --- /dev/null +++ b/3rdparty/icons/breeze-dark/actions/24/format-text-strikethrough.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/3rdparty/icons/breeze/actions/16/format-text-strikethrough.svg b/3rdparty/icons/breeze/actions/16/format-text-strikethrough.svg new file mode 100644 index 00000000..752b962d --- /dev/null +++ b/3rdparty/icons/breeze/actions/16/format-text-strikethrough.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/3rdparty/icons/breeze/actions/22/format-text-strikethrough.svg b/3rdparty/icons/breeze/actions/22/format-text-strikethrough.svg new file mode 100644 index 00000000..7f0cfc45 --- /dev/null +++ b/3rdparty/icons/breeze/actions/22/format-text-strikethrough.svg @@ -0,0 +1,14 @@ + + + + + + diff --git a/3rdparty/icons/breeze/actions/24/format-text-strikethrough.svg b/3rdparty/icons/breeze/actions/24/format-text-strikethrough.svg new file mode 100644 index 00000000..27b4f303 --- /dev/null +++ b/3rdparty/icons/breeze/actions/24/format-text-strikethrough.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/3rdparty/icons/oxygen/16x16/actions/format-text-strikethrough.png b/3rdparty/icons/oxygen/16x16/actions/format-text-strikethrough.png new file mode 100644 index 0000000000000000000000000000000000000000..f248ce09cb714c357e0ce28715b5c692aa817c90 GIT binary patch literal 441 zcmV;q0Y?6bP)MzCV_|S* zE^l&Yo9;Xs0003vNklMrKNhJ?s3A-(Ng~ur^Abjp`GmKNAAvl}Iq!M+otI-k$7S4{JBWr0 z@$aY_y4wqRrvBdbvDLH`^OK`Ql~;;n*m&s?l=T2AY0gMA5+teOp+}JW5^s2G$D;wG z-|V|Av(hbyNom%3XREn8)9SYsPt#famr&uWwfSc)xH^HsIc^_r3+{-UK14LZPNU5S zHJ*9mLBozFSRxkspe1x6L*kH>lO$Tu$>RF;l zv?B~!xj|H!*1A~-Wqim^kMPJjE~Fx=lPhkq)y3QqjLNl_7+LZZ$Pi@VQ|5awIU>t) jDmkf1RZ?;&W9XA#BMzCV_|S* zE^l&Yo9;Xs0005PNklXH>gXq!Po`ys|0ZR|%gyIz>?q&eDP&D$*MfZc;3 z@9H}|e2a5V8Ea_exUTa+{I2u5-%l?0drmsu*LkUZn-)j5wx{m!hACV;T&Bq|g#D?m zJb+JBMc%(4%NR)pOK6x8JhIqW8v^+7l|FJMbS;&r?cM%hi?cs*>mfPXI1Kjk7 zip_(~jZK@hIBK=9dQnT^Fh5aIAkQ3MndLK+e+r{;jdhUKt5KU*bg0T`Ihwsnl5x_E z(uL8b`x~mdjmF84f1h_`c!CTCutcRO9jH09w}B}>FpA6vu=yj!v7%I}?d7sO&NR=F z2@M|O9L7F1?>UZ#%Oea&gEKs)-Zw4T720Wp#qGt%C4yP2!4tT=jMcbn%8M@D2;7UZKbV0MRg{QEc7&~LjOMic(S R%ZUI0002ovPDHLkV1hht2TA|{ literal 0 HcmV?d00001 diff --git a/3rdparty/icons/oxygen/32x32/actions/format-text-strikethrough.png b/3rdparty/icons/oxygen/32x32/actions/format-text-strikethrough.png new file mode 100644 index 0000000000000000000000000000000000000000..d062ee7b3f48a44469e4de66380999e532f6b158 GIT binary patch literal 1359 zcmX|93rv$&82v@T%BBQoj3RC(y2Me%M|7J*9U=tCv>G0x&=&erXn6{@Wt9Q}q0p7b z7*Jq<6v3egOkP@AK*kIZc?^(;NTJYDpp-&^0_7o(eWuB7@}GO|`OdxfKVL5IF3x_x zv6(S~Ap0F1Y@J{}@#(|t2DJS%u@$D>3>!xm3|ajumuQsfQN^NgCQ*~Ej2Y2Jpb$Y`T2S?kH-V2o&&nLxB$}Wbl3}eUS1xc zzrQ~qgTVlVDjWr*q@+Z@1OvcY-|Jq(Na=UpajIn#|K2cEif>UMxz0OXKHFntyV)2eF;wU z^78Wb_6CEWpC5EJBqRg^LL4TO30;L2vDxg%$jIpEXby)HA0MBPkO2Rgl$4a5oD8kY z&d!ED2n2${!os4WA_)Hc`SY@}vhwnB2vSv5Rb5?OQ&S@p3Tta?AqB*#tE;Q8uWx8* zc>VfyQ&UrOb8}l;TSrGncXxMBPtUt|?|OTC`}+F&`}+q52HwAaKR7t};lqcap&^Mx zGCVvyGBP5SN=HXW$HvBFGMQX1A0HoAC=?SD6O)sZ5KyU9PESv(RH~Vo83;Q&J3BWw zr_pHU=jRs|78Vy5wOZ}c($ezs^2*AJPN!R4U0qvSTVG$_*x2~^@#E&^X5d*48y+i@ z>4bAe40i7^G&C~8e15?6@DUhCkC~r5Wr00=?!v`yzx%<;{?_d~PEO8l1TxJ(Ae7Ex z!yAp~a(RiV>HMsm+`NKkrDf$WUkM?+7$U!E|F^5Fe;6W+$>ie-rCPnPpw;Tu*5L9_ zw{LB2Z*Ny@pUFg!T`i8bH(b8&ppYM1kOy9_ro6@RjCB{C<*j_`AWu+FRSV+w>NFz_ zO!kS->aJ!e`N3S%$8leg9=32!+MAp!xE9sEy#AB!_%%u53+u+op2eF{_uA794wed4 z*xv@13cop@8#dm2347Z9{u`c!=Osf8_D+7lp*Xt87?RvpKb%8lC#d$YR=u7uAnY+tjgjk|G$_z>OqGx=Bf;RE~s-aNY3B$!ac9_T!U z&NiC%r>H!{=$7R2oRR2iC)z6t=xbg1g4EMuiqfRw;Etz;X(igMVzlVI&|y+IN67Yl zJX3*}1{x?TCxb>_QBX{7>|aZpsJW_iD}r_V7hC7bC`#@bzCsf1wtBK@=S?<+(s0y%F-0iaPvPh*53>{ zC#lVQ;_R`Fg)B|!P1?CfV>LlILW}_wx!68^#qjGa*Qtbv;nVUiLGq){Q&c}>Q`K83 THSgO44+?R#!`Z&DA;MzCV_|S* zE^l&Yo9;Xs000BhNklx#Mfr7*%wN=Yqxbbd~ zm10Z@Q2==fpV~U`;Ai7J6p_D8H(=VD+xk0`t2ybUjV2msq=il_c(iZ46hs4LoTy_; z%SQ|4!HVjtEc5F%JFAn-Vm?^jP`Ugo?(nzyWa|aecN8+ov{pSu4M(3@f6bxopPjB^ z8b9yr2Nc6O0$N?fOXT|}(v-ZvhI8IZQ?I~MNBK{cvNElhhMCP3ExhCVxs>+*Af{YbwY zm87VETvIMF$P^LCW_iOF2{O+dGfd&fiyIeC9N4g~DVvBu#=m;_G?V!7Fu^!u*s-oF zBQl_F?%`T$WFXa)!sbgg=|1#L_ervxGR&D7VhOa*0zL-$lRvnCAz(<{^w?r}NZyhk zGlO+FRvM&_UjACC2Mb>#?Q!ujnTt{$l{};0OfLf~^=piU_mHHR02)$KKrcfKt|G-K z`(irT$)S(w3*BUxp)hh1F~@jxRL^|DC?nhqucQg(YK#HnHkARajIy#0x>18V0M#U{ z)FO{;xCT!Lc5LBwbRaGrfH2Gmhfz}_KmOINve?5Ijxcc^xugpi!O9t=JTjm@zZ)0h z+ICls@|7-N6dN6gB{Cqn1*^M~gJRT7U4Ruk4l+Z^YY}F@XC=^yPa|xhy~xYD02>aR zw6kYXO46TT{m=89v{$S-73z^L;&cIa#u#UULCQ#Mg{EYGwhsg-Zgt*fAh%!c)XO=*C4X)4u7%Xaz^7y7+V^g-MFDY44qMVa1=@q;9q+k76O4S^BGkwRsH~s$y Z@HaT=sj_fGVo?A9002ovPDHLkV1g5e`qKaa literal 0 HcmV?d00001 diff --git a/data/stylesheets/m4yer.qss b/data/stylesheets/m4yer.qss index 163eff5d..eb79149b 100644 --- a/data/stylesheets/m4yer.qss +++ b/data/stylesheets/m4yer.qss @@ -84,11 +84,13 @@ ChatLine[bg-color="0f"] { background: #c0c0c0; } ChatLine[format="bold"] { font-weight: bold;} ChatLine[format="italic"] { font-style: italic; } ChatLine[format="underline"] { font-style: underline; } +ChatLine[format="strikethrough"] { font-style: strikethrough; } // for sender ChatLine[format="bold", sender="self"] { foreground: #323232; font-weight: bold; } ChatLine[format="italic", sender="self"] { foreground: #323232; font-style: italic; } ChatLine[format="underline", sender="self"] { foreground: #323232; font-style: underline; } + ChatLine[format="strikethrough", sender="self"] { foreground: #323232; font-style: strikethrough; } // ChatView message colors ChatLine#notice { foreground: #916409; } diff --git a/src/qtui/inputwidget.cpp b/src/qtui/inputwidget.cpp index ad837166..69986724 100644 --- a/src/qtui/inputwidget.cpp +++ b/src/qtui/inputwidget.cpp @@ -68,6 +68,7 @@ InputWidget::InputWidget(QWidget* parent) ui.boldButton->setIcon(icon::get("format-text-bold")); ui.italicButton->setIcon(icon::get("format-text-italic")); ui.underlineButton->setIcon(icon::get("format-text-underline")); + ui.strikethroughButton->setIcon(icon::get("format-text-strikethrough")); ui.clearButton->setIcon(icon::get("edit-clear")); ui.encryptionIconLabel->hide(); @@ -374,6 +375,11 @@ void InputWidget::toggleFormatUnderline() setFormatUnderline(!ui.underlineButton->isChecked()); } +void InputWidget::toggleFormatStrikethrough() +{ + setFormatStrikethrough(!ui.strikethroughButton->isChecked()); +} + void InputWidget::clearFormat() { // Clear all formatting for selection (not global) @@ -511,6 +517,7 @@ void InputWidget::setFormatClear(const bool global) QTextCharFormat fmt; fmt.setFontWeight(QFont::Normal); fmt.setFontUnderline(false); + fmt.setFontStrikeOut(false); fmt.setFontItalic(false); fmt.clearForeground(); fmt.clearBackground(); @@ -525,6 +532,7 @@ void InputWidget::setFormatClear(const bool global) ui.boldButton->setChecked(false); ui.italicButton->setChecked(false); ui.underlineButton->setChecked(false); + ui.strikethroughButton->setChecked(false); } void InputWidget::setFormatBold(const bool bold) @@ -557,6 +565,16 @@ void InputWidget::setFormatUnderline(const bool underline) ui.underlineButton->setChecked(underline); } +void InputWidget::setFormatStrikethrough(const bool strike) +{ + // Apply formatting + QTextCharFormat fmt; + fmt.setFontStrikeOut(strike); + mergeFormatOnSelection(fmt); + // Make sure UI state follows + ui.strikethroughButton->setChecked(strike); +} + void InputWidget::mergeFormatOnSelection(const QTextCharFormat& format) { QTextCursor cursor = inputLine()->textCursor(); @@ -605,6 +623,11 @@ void InputWidget::on_underlineButton_clicked(bool checked) setFormatUnderline(checked); } +void InputWidget::on_strikethroughButton_clicked(bool checked) +{ + setFormatStrikethrough(checked); +} + void InputWidget::on_italicButton_clicked(bool checked) { setFormatItalic(checked); @@ -615,6 +638,7 @@ void InputWidget::fontChanged(const QFont& f) ui.boldButton->setChecked(f.bold()); ui.italicButton->setChecked(f.italic()); ui.underlineButton->setChecked(f.underline()); + ui.strikethroughButton->setChecked(f.strikeOut()); } void InputWidget::colorChosen(QAction* action) diff --git a/src/qtui/inputwidget.h b/src/qtui/inputwidget.h index b6afaee0..ad209596 100644 --- a/src/qtui/inputwidget.h +++ b/src/qtui/inputwidget.h @@ -83,6 +83,13 @@ public slots: */ void toggleFormatUnderline(); + /** + * Toggle the striking of the selected or typed text + * + * striking becomes normal, and normal becomes underlined. + */ + void toggleFormatStrikethrough(); + /** * Clear the formatting of the selected or typed text * @@ -132,6 +139,7 @@ private slots: void on_boldButton_clicked(bool checked); void on_italicButton_clicked(bool checked); void on_underlineButton_clicked(bool checked); + void on_strikethroughButton_clicked(bool checked); void colorChosen(QAction* action); void colorHighlightChosen(QAction* action); @@ -166,6 +174,13 @@ private: */ void setFormatUnderline(const bool underline); + /** + * Sets the strikethrough of the selected or typed text + * + * @param strike If true, set text striked, otherwise set text normal + */ + void setFormatStrikethrough(const bool strike); + Ui::InputWidget ui; NetworkId _networkId; diff --git a/src/qtui/inputwidget.ui b/src/qtui/inputwidget.ui index 24a25255..631aa757 100644 --- a/src/qtui/inputwidget.ui +++ b/src/qtui/inputwidget.ui @@ -274,6 +274,49 @@ + + + + true + + + + 0 + 0 + + + + + 26 + 24 + + + + + 16777215 + 16777215 + + + + Strikethrough + + + + + + + 16 + 16 + + + + true + + + false + + + diff --git a/src/qtui/mainwin.cpp b/src/qtui/mainwin.cpp index dae50296..019216fd 100644 --- a/src/qtui/mainwin.cpp +++ b/src/qtui/mainwin.cpp @@ -466,7 +466,14 @@ void MainWin::setupActions() coll, this, &MainWin::onFormatUnderlineTriggered, - QKeySequence::Underline)}}); + QKeySequence::Underline)}, + {"FormatStrikethrough", + new Action(icon::get("format-text-strikethrough"), + tr("Toggle strikethrough"), + coll, + this, + &MainWin::onFormatStrikethroughTriggered, + QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_S))}}); // Navigation coll = QtUi::actionCollection("Navigation", tr("Navigation")); @@ -1834,6 +1841,15 @@ void MainWin::onFormatUnderlineTriggered() _inputWidget->toggleFormatUnderline(); } +void MainWin::onFormatStrikethroughTriggered() +{ + if (!_inputWidget) + return; + + _inputWidget->toggleFormatStrikethrough(); +} + + void MainWin::onJumpHotBufferTriggered() { if (!_bufferHotList->rowCount()) diff --git a/src/qtui/mainwin.h b/src/qtui/mainwin.h index fbcd553a..0ff2a36f 100644 --- a/src/qtui/mainwin.h +++ b/src/qtui/mainwin.h @@ -189,6 +189,13 @@ private slots: */ void onFormatUnderlineTriggered(); + /** + * Toggle the strikethrough of the input widget selected or typed text + * + * @seealso InputWidget::toggleFormatStrikethrough() + */ + void onFormatStrikethroughTriggered(); + /** * Clear the formatting of the input widget selected or typed text * diff --git a/src/uisupport/multilineedit.cpp b/src/uisupport/multilineedit.cpp index 1ecba103..1712cc6f 100644 --- a/src/uisupport/multilineedit.cpp +++ b/src/uisupport/multilineedit.cpp @@ -463,13 +463,13 @@ void MultiLineEdit::keyPressEvent(QKeyEvent* event) QString MultiLineEdit::convertRichtextToMircCodes() { - bool underline, bold, italic, color; + bool underline, bold, italic, color, strikethrough; QString mircText, mircFgColor, mircBgColor; QTextCursor cursor = textCursor(); QTextCursor peekcursor = textCursor(); cursor.movePosition(QTextCursor::Start); - underline = bold = italic = color = false; + underline = bold = italic = color = strikethrough = false; while (cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor)) { if (cursor.selectedText() == QString(QChar(QChar::LineSeparator)) @@ -490,6 +490,10 @@ QString MultiLineEdit::convertRichtextToMircCodes() bold = false; mircText.append('\x02'); } + if (strikethrough) { + strikethrough = false; + mircText.append('\x1E'); + } mircText.append('\n'); } else { @@ -505,6 +509,10 @@ QString MultiLineEdit::convertRichtextToMircCodes() underline = true; mircText.append('\x1f'); } + if (!strikethrough && cursor.charFormat().fontStrikeOut()) { + strikethrough = true; + mircText.append('\x1E'); + } if (!color && (cursor.charFormat().foreground().isOpaque() || cursor.charFormat().background().isOpaque())) { color = true; mircText.append('\x03'); @@ -542,6 +550,10 @@ QString MultiLineEdit::convertRichtextToMircCodes() bold = false; mircText.append('\x02'); } + if (strikethrough) { + strikethrough = false; + mircText.append('\x1E'); + } } } @@ -560,6 +572,9 @@ QString MultiLineEdit::convertRichtextToMircCodes() if (bold) mircText.append('\x02'); + if (strikethrough) + mircText.append('\x1E'); + return mircText; } @@ -572,6 +587,8 @@ bool MultiLineEdit::mircCodesChanged(QTextCursor& cursor, QTextCursor& peekcurso changed = true; if (cursor.charFormat().fontUnderline() != peekcursor.charFormat().fontUnderline()) changed = true; + if (cursor.charFormat().fontStrikeOut() != peekcursor.charFormat().fontStrikeOut()) + changed = true; if (cursor.charFormat().foreground().color() != peekcursor.charFormat().foreground().color()) changed = true; if (cursor.charFormat().background().color() != peekcursor.charFormat().background().color()) @@ -582,7 +599,7 @@ bool MultiLineEdit::mircCodesChanged(QTextCursor& cursor, QTextCursor& peekcurso QString MultiLineEdit::convertMircCodesToHtml(const QString& text) { QStringList words; - QRegExp mircCode = QRegExp("(|||)", Qt::CaseSensitive); + QRegExp mircCode = QRegExp("(\x02|\x1d|\x1f|\x03|\x1E)", Qt::CaseSensitive); int posLeft = 0; int posRight = 0; @@ -623,6 +640,10 @@ QString MultiLineEdit::convertMircCodesToHtml(const QString& text) style.append(" text-decoration: underline;"); words[i].replace('\x1f', ""); } + if (words[i].contains('\x1E')) { + style.append(" text-decoration: line-through;"); + words[i].replace('\x1E', ""); + } if (words[i].contains('\x03')) { int pos = words[i].indexOf('\x03'); int len = 3; -- 2.20.1