1 //=============================================================================
2 // MusE Score
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2002-2010 Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "log.h"
21
22 #include "texttools.h"
23 #include "icons.h"
24 #include "libmscore/text.h"
25 #include "musescore.h"
26 #include "libmscore/score.h"
27 #include "textpalette.h"
28 #include "libmscore/mscore.h"
29 #include "preferences.h"
30 #include "scoreview.h"
31
32 namespace Ms {
33
34 TextPalette* textPalette;
35
36 //---------------------------------------------------------
37 // textTools
38 //---------------------------------------------------------
39
textTools()40 TextTools* MuseScore::textTools()
41 {
42 if (!_textTools) {
43 _textTools = new TextTools(this);
44 addDockWidget(Qt::DockWidgetArea(Qt::BottomDockWidgetArea), _textTools);
45 }
46 setFocusPolicy(Qt::NoFocus);
47 return _textTools;
48 }
49
50 //---------------------------------------------------------
51 // TextTools
52 //---------------------------------------------------------
53
TextTools(QWidget * parent)54 TextTools::TextTools(QWidget* parent)
55 : QDockWidget(parent)
56 {
57 setObjectName("text-tools");
58 setAllowedAreas(Qt::DockWidgetAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea));
59 setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
60
61 text = nullptr;
62 cursor = nullptr;
63
64 toolbar = new QToolBar(tr("Text Edit"));
65 toolbar->setIconSize(QSize(preferences.getInt(PREF_UI_THEME_ICONWIDTH) * guiScaling,
66 preferences.getInt(PREF_UI_THEME_ICONHEIGHT) * guiScaling));
67
68 showKeyboard = getAction("show-keys");
69 showKeyboard->setCheckable(true);
70 toolbar->addAction(showKeyboard);
71
72 typefaceBold = toolbar->addAction(*icons[int(Icons::textBold_ICON)], "");
73 typefaceBold->setCheckable(true);
74
75 typefaceItalic = toolbar->addAction(*icons[int(Icons::textItalic_ICON)], "");
76 typefaceItalic->setCheckable(true);
77
78 typefaceUnderline = toolbar->addAction(*icons[int(Icons::textUnderline_ICON)], "");
79 typefaceUnderline->setCheckable(true);
80
81 toolbar->addSeparator();
82
83 typefaceSubscript = toolbar->addAction(*icons[int(Icons::textSub_ICON)], "");
84 typefaceSubscript->setCheckable(true);
85
86 typefaceSuperscript = toolbar->addAction(*icons[int(Icons::textSuper_ICON)], "");
87 typefaceSuperscript->setCheckable(true);
88
89 toolbar->addSeparator();
90
91 typefaceFamily = new QFontComboBox(this);
92 typefaceFamily->setEditable(false);
93 toolbar->addWidget(typefaceFamily);
94
95 typefaceSize = new QDoubleSpinBox(this);
96 typefaceSize->setFocusPolicy(Qt::ClickFocus);
97 typefaceSize->setMinimum(1);
98 toolbar->addWidget(typefaceSize);
99
100 setWidget(toolbar);
101 QWidget* w = new QWidget(this);
102 setTitleBarWidget(w);
103 titleBarWidget()->hide();
104
105 connect(typefaceSize, SIGNAL(valueChanged(double)), SLOT(sizeChanged(double)));
106 connect(typefaceFamily, SIGNAL(currentFontChanged(const QFont&)), SLOT(fontChanged(const QFont&)));
107 connect(typefaceBold, SIGNAL(triggered(bool)), SLOT(boldClicked(bool)));
108 connect(typefaceItalic, SIGNAL(triggered(bool)), SLOT(italicClicked(bool)));
109 connect(typefaceUnderline, SIGNAL(triggered(bool)), SLOT(underlineClicked(bool)));
110 connect(typefaceSubscript, SIGNAL(triggered(bool)), SLOT(subscriptClicked(bool)));
111 connect(typefaceSuperscript, SIGNAL(triggered(bool)), SLOT(superscriptClicked(bool)));
112 connect(showKeyboard, SIGNAL(toggled(bool)), SLOT(showKeyboardClicked(bool)));
113
114 retranslate();
115 }
116
117 //---------------------------------------------------------
118 // retranslate
119 //---------------------------------------------------------
120
retranslate()121 void TextTools::retranslate()
122 {
123 setWindowTitle(tr("Text Tools"));
124 toolbar->setWindowTitle(tr("Text Edit"));
125 typefaceBold->setToolTip(tr("Bold"));
126 typefaceItalic->setToolTip(tr("Italic"));
127 typefaceSubscript->setToolTip(tr("Subscript"));
128 typefaceSuperscript->setToolTip(tr("Superscript"));
129 }
130
131 //---------------------------------------------------------
132 // changeEvent
133 //---------------------------------------------------------
134
changeEvent(QEvent * event)135 void TextTools::changeEvent(QEvent* event)
136 {
137 QDockWidget::changeEvent(event);
138 if (event->type() == QEvent::LanguageChange)
139 retranslate();
140 }
141
142 //---------------------------------------------------------
143 // blockAllSignals
144 //---------------------------------------------------------
145
blockAllSignals(bool val)146 void TextTools::blockAllSignals(bool val)
147 {
148 typefaceSize->blockSignals(val);
149 typefaceFamily->blockSignals(val);
150 typefaceBold->blockSignals(val);
151 typefaceItalic->blockSignals(val);
152 typefaceUnderline->blockSignals(val);
153 typefaceSubscript->blockSignals(val);
154 typefaceSuperscript->blockSignals(val);
155 typefaceFamily->blockSignals(val);
156 showKeyboard->blockSignals(val);
157 }
158
159 //---------------------------------------------------------
160 // updateTools
161 //---------------------------------------------------------
162
updateTools(EditData & ed)163 void TextTools::updateTools(EditData& ed)
164 {
165 text = toTextBase(ed.element);
166 IF_ASSERT_FAILED(text) {
167 return;
168 }
169
170 cursor = text->cursor(ed);
171 IF_ASSERT_FAILED(cursor) {
172 return;
173 }
174
175 blockAllSignals(true);
176 CharFormat* format = cursor->format();
177
178 QFont f(format->fontFamily());
179 typefaceFamily->setCurrentFont(f);
180 typefaceFamily->setEnabled(true);
181 typefaceSize->setValue(format->fontSize());
182
183 typefaceItalic->setChecked(format->italic());
184 typefaceBold->setChecked(format->bold());
185 typefaceUnderline->setChecked(format->underline());
186 typefaceSubscript->setChecked(format->valign() == VerticalAlignment::AlignSubScript);
187 typefaceSuperscript->setChecked(format->valign() == VerticalAlignment::AlignSuperScript);
188
189 blockAllSignals(false);
190 }
191
192 //---------------------------------------------------------
193 // updateText
194 //---------------------------------------------------------
195
updateText()196 void TextTools::updateText()
197 {
198 if (!text)
199 return;
200 layoutText();
201 }
202
203 //---------------------------------------------------------
204 // layoutText
205 //---------------------------------------------------------
206
layoutText()207 void TextTools::layoutText()
208 {
209 text->triggerLayout();
210 text->score()->update();
211 }
212
213 //---------------------------------------------------------
214 // sizeChanged
215 //---------------------------------------------------------
216
sizeChanged(double value)217 void TextTools::sizeChanged(double value)
218 {
219 IF_ASSERT_FAILED(cursor) {
220 return;
221 }
222 cursor->setFormat(FormatId::FontSize, value);
223 cursor->format()->setFontSize(value);
224 updateText();
225 }
226
227 //---------------------------------------------------------
228 // fontChanged
229 //---------------------------------------------------------
230
fontChanged(const QFont & f)231 void TextTools::fontChanged(const QFont& f)
232 {
233 //! REVIEW An explanation is needed why only in this one method
234 //! it is assumed that the cursor may not be,
235 //! and that this is a normal situation, and not an exception (no assertion)
236 if (cursor)
237 cursor->setFormat(FormatId::FontFamily, f.family());
238 if (textPalette)
239 textPalette->setFont(f.family());
240 updateText();
241 }
242
243 //---------------------------------------------------------
244 // boldClicked
245 //---------------------------------------------------------
246
boldClicked(bool val)247 void TextTools::boldClicked(bool val)
248 {
249 IF_ASSERT_FAILED(cursor) {
250 return;
251 }
252 cursor->setFormat(FormatId::Bold, val);
253 updateText();
254 }
255
256 //---------------------------------------------------------
257 // toggleBold
258 //---------------------------------------------------------
259
toggleBold()260 void TextTools::toggleBold()
261 {
262 typefaceBold->toggle();
263 boldClicked(typefaceBold->isChecked());
264 }
265
266 //---------------------------------------------------------
267 // toggleItalic
268 //---------------------------------------------------------
269
toggleItalic()270 void TextTools::toggleItalic()
271 {
272 typefaceItalic->toggle();
273 italicClicked(typefaceItalic->isChecked());
274 }
275
276 //---------------------------------------------------------
277 // toggleUnderline
278 //---------------------------------------------------------
279
toggleUnderline()280 void TextTools::toggleUnderline()
281 {
282 typefaceUnderline->toggle();
283 underlineClicked(typefaceUnderline->isChecked());
284 }
285
286 //---------------------------------------------------------
287 // underlineClicked
288 //---------------------------------------------------------
289
underlineClicked(bool val)290 void TextTools::underlineClicked(bool val)
291 {
292 IF_ASSERT_FAILED(cursor) {
293 return;
294 }
295 cursor->setFormat(FormatId::Underline, val);
296 updateText();
297 }
298
299 //---------------------------------------------------------
300 // italicClicked
301 //---------------------------------------------------------
302
italicClicked(bool val)303 void TextTools::italicClicked(bool val)
304 {
305 IF_ASSERT_FAILED(cursor) {
306 return;
307 }
308 cursor->setFormat(FormatId::Italic, val);
309 updateText();
310 }
311
312 //---------------------------------------------------------
313 // subscriptClicked
314 //---------------------------------------------------------
315
subscriptClicked(bool val)316 void TextTools::subscriptClicked(bool val)
317 {
318 IF_ASSERT_FAILED(cursor) {
319 return;
320 }
321 cursor->setFormat(FormatId::Valign, int(val ? VerticalAlignment::AlignSubScript : VerticalAlignment::AlignNormal));
322 typefaceSuperscript->blockSignals(true);
323 typefaceSuperscript->setChecked(false);
324 typefaceSuperscript->blockSignals(false);
325 updateText();
326 }
327
328 //---------------------------------------------------------
329 // superscriptClicked
330 //---------------------------------------------------------
331
superscriptClicked(bool val)332 void TextTools::superscriptClicked(bool val)
333 {
334 IF_ASSERT_FAILED(cursor) {
335 return;
336 }
337 cursor->setFormat(FormatId::Valign, int(val ? VerticalAlignment::AlignSuperScript : VerticalAlignment::AlignNormal));
338 typefaceSubscript->blockSignals(true);
339 typefaceSubscript->setChecked(false);
340 typefaceSubscript->blockSignals(false);
341 updateText();
342 }
343
344 //---------------------------------------------------------
345 // showKeyboardClicked
346 //---------------------------------------------------------
347
showKeyboardClicked(bool val)348 void TextTools::showKeyboardClicked(bool val)
349 {
350 if (val) {
351 IF_ASSERT_FAILED(cursor) {
352 return;
353 }
354 if (textPalette == 0)
355 textPalette = new TextPalette(mscore);
356 textPalette->setText(text);
357 textPalette->setFont(cursor->format()->fontFamily());
358 textPalette->show();
359 }
360 else {
361 if (textPalette)
362 textPalette->hide();
363 }
364 }
365 }
366