1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 by the Quassel Project * |
3 | * devel@quassel-irc.org * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) version 3. * |
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 * |
17 | * Free Software Foundation, Inc., * |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
19 | ***************************************************************************/ |
20 | |
21 | #include "inputwidget.h" |
22 | |
23 | #include "action.h" |
24 | #include "actioncollection.h" |
25 | #include "bufferview.h" |
26 | #include "client.h" |
27 | #include "iconloader.h" |
28 | #include "ircuser.h" |
29 | #include "networkmodel.h" |
30 | #include "qtui.h" |
31 | #include "qtuisettings.h" |
32 | #include "tabcompleter.h" |
33 | #include <QPainter> |
34 | |
35 | const int leftMargin = 3; |
36 | |
37 | InputWidget::InputWidget(QWidget *parent) |
38 | : AbstractItemView(parent), |
39 | _networkId(0) |
40 | { |
41 | ui.setupUi(this); |
42 | connect(ui.ownNick, SIGNAL(activated(QString)), this, SLOT(changeNick(QString))); |
43 | |
44 | layout()->setAlignment(ui.ownNick, Qt::AlignBottom); |
45 | layout()->setAlignment(ui.inputEdit, Qt::AlignBottom); |
46 | layout()->setAlignment(ui.showStyleButton, Qt::AlignBottom); |
47 | layout()->setAlignment(ui.styleFrame, Qt::AlignBottom); |
48 | |
49 | ui.styleFrame->setVisible(false); |
50 | |
51 | setFocusProxy(ui.inputEdit); |
52 | ui.ownNick->setFocusProxy(ui.inputEdit); |
53 | |
54 | ui.ownNick->setSizeAdjustPolicy(QComboBox::AdjustToContents); |
55 | ui.ownNick->installEventFilter(new MouseWheelFilter(this)); |
56 | ui.inputEdit->installEventFilter(this); |
57 | |
58 | ui.inputEdit->setMinHeight(1); |
59 | ui.inputEdit->setMaxHeight(5); |
60 | ui.inputEdit->setMode(MultiLineEdit::MultiLine); |
61 | ui.inputEdit->setPasteProtectionEnabled(true); |
62 | |
63 | ui.boldButton->setIcon(SmallIcon("format-text-bold" )); |
64 | ui.italicButton->setIcon(SmallIcon("format-text-italic" )); |
65 | ui.underlineButton->setIcon(SmallIcon("format-text-underline" )); |
66 | ui.textcolorButton->setIcon(SmallIcon("format-text-color" )); |
67 | ui.highlightcolorButton->setIcon(SmallIcon("format-fill-color" )); |
68 | ui.encryptionIconLabel->hide(); |
69 | |
70 | _colorMenu = new QMenu(); |
71 | _colorFillMenu = new QMenu(); |
72 | |
73 | QStringList names; |
74 | names << tr("White" ) << tr("Black" ) << tr("Dark blue" ) << tr("Dark green" ) << tr("Red" ) << tr("Dark red" ) << tr("Dark magenta" ) << tr("Orange" ) |
75 | << tr("Yellow" ) << tr("Green" ) << tr("Dark cyan" ) << tr("Cyan" ) << tr("Blue" ) << tr("Magenta" ) << tr("Dark gray" ) << tr("Light gray" ); |
76 | |
77 | QPixmap pix(16, 16); |
78 | for (int i = 0; i < inputLine()->mircColorMap().count(); i++) { |
79 | pix.fill(inputLine()->mircColorMap().values()[i]); |
80 | _colorMenu->addAction(pix, names[i])->setData(inputLine()->mircColorMap().keys()[i]); |
81 | _colorFillMenu->addAction(pix, names[i])->setData(inputLine()->mircColorMap().keys()[i]); |
82 | } |
83 | |
84 | pix.fill(Qt::transparent); |
85 | _colorMenu->addAction(pix, tr("Clear Color" ))->setData("" ); |
86 | _colorFillMenu->addAction(pix, tr("Clear Color" ))->setData("" ); |
87 | |
88 | ui.textcolorButton->setMenu(_colorMenu); |
89 | connect(_colorMenu, SIGNAL(triggered(QAction *)), this, SLOT(colorChosen(QAction *))); |
90 | ui.highlightcolorButton->setMenu(_colorFillMenu); |
91 | connect(_colorFillMenu, SIGNAL(triggered(QAction *)), this, SLOT(colorHighlightChosen(QAction *))); |
92 | |
93 | new TabCompleter(ui.inputEdit); |
94 | |
95 | UiStyleSettings fs("Fonts" ); |
96 | fs.notify("UseCustomInputWidgetFont" , this, SLOT(setUseCustomFont(QVariant))); |
97 | fs.notify("InputWidget" , this, SLOT(setCustomFont(QVariant))); |
98 | if (fs.value("UseCustomInputWidgetFont" , false).toBool()) |
99 | setCustomFont(fs.value("InputWidget" , QFont())); |
100 | |
101 | UiSettings s("InputWidget" ); |
102 | |
103 | #ifdef HAVE_KDE |
104 | s.notify("EnableSpellCheck" , this, SLOT(setEnableSpellCheck(QVariant))); |
105 | setEnableSpellCheck(s.value("EnableSpellCheck" , false)); |
106 | #endif |
107 | |
108 | s.notify("EnableEmacsMode" , this, SLOT(setEnableEmacsMode(QVariant))); |
109 | setEnableEmacsMode(s.value("EnableEmacsMode" , false)); |
110 | |
111 | s.notify("ShowNickSelector" , this, SLOT(setShowNickSelector(QVariant))); |
112 | setShowNickSelector(s.value("ShowNickSelector" , true)); |
113 | |
114 | s.notify("ShowStyleButtons" , this, SLOT(setShowStyleButtons(QVariant))); |
115 | setShowStyleButtons(s.value("ShowStyleButtons" , true)); |
116 | |
117 | s.notify("EnablePerChatHistory" , this, SLOT(setEnablePerChatHistory(QVariant))); |
118 | setEnablePerChatHistory(s.value("EnablePerChatHistory" , false)); |
119 | |
120 | s.notify("MaxNumLines" , this, SLOT(setMaxLines(QVariant))); |
121 | setMaxLines(s.value("MaxNumLines" , 5)); |
122 | |
123 | s.notify("EnableScrollBars" , this, SLOT(setScrollBarsEnabled(QVariant))); |
124 | setScrollBarsEnabled(s.value("EnableScrollBars" , true)); |
125 | |
126 | s.notify("EnableLineWrap" , this, SLOT(setLineWrapEnabled(QVariant))); |
127 | setLineWrapEnabled(s.value("EnableLineWrap" , false)); |
128 | |
129 | s.notify("EnableMultiLine" , this, SLOT(setMultiLineEnabled(QVariant))); |
130 | setMultiLineEnabled(s.value("EnableMultiLine" , true)); |
131 | |
132 | ActionCollection *coll = QtUi::actionCollection(); |
133 | |
134 | Action *activateInputline = coll->add<Action>("FocusInputLine" ); |
135 | connect(activateInputline, SIGNAL(triggered()), SLOT(setFocus())); |
136 | activateInputline->setText(tr("Focus Input Line" )); |
137 | activateInputline->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); |
138 | |
139 | connect(inputLine(), SIGNAL(textEntered(QString)), SLOT(onTextEntered(QString)), Qt::QueuedConnection); // make sure the line is already reset, bug #984 |
140 | connect(inputLine(), SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SLOT(currentCharFormatChanged(QTextCharFormat))); |
141 | } |
142 | |
143 | |
144 | InputWidget::~InputWidget() |
145 | { |
146 | } |
147 | |
148 | |
149 | void InputWidget::setUseCustomFont(const QVariant &v) |
150 | { |
151 | if (v.toBool()) { |
152 | UiStyleSettings fs("Fonts" ); |
153 | setCustomFont(fs.value("InputWidget" )); |
154 | } |
155 | else |
156 | setCustomFont(QFont()); |
157 | } |
158 | |
159 | |
160 | void InputWidget::setCustomFont(const QVariant &v) |
161 | { |
162 | QFont font = v.value<QFont>(); |
163 | if (font.family().isEmpty()) |
164 | font = QApplication::font(); |
165 | // we don't want font styles as this conflics with mirc code richtext editing |
166 | font.setBold(false); |
167 | font.setItalic(false); |
168 | font.setUnderline(false); |
169 | font.setStrikeOut(false); |
170 | ui.inputEdit->setCustomFont(font); |
171 | } |
172 | |
173 | |
174 | void InputWidget::setEnableSpellCheck(const QVariant &v) |
175 | { |
176 | ui.inputEdit->setSpellCheckEnabled(v.toBool()); |
177 | } |
178 | |
179 | |
180 | void InputWidget::setEnableEmacsMode(const QVariant &v) |
181 | { |
182 | ui.inputEdit->setEmacsMode(v.toBool()); |
183 | } |
184 | |
185 | |
186 | void InputWidget::setShowNickSelector(const QVariant &v) |
187 | { |
188 | ui.ownNick->setVisible(v.toBool()); |
189 | } |
190 | |
191 | |
192 | void InputWidget::setShowStyleButtons(const QVariant &v) |
193 | { |
194 | ui.showStyleButton->setVisible(v.toBool()); |
195 | } |
196 | |
197 | |
198 | void InputWidget::setEnablePerChatHistory(const QVariant &v) |
199 | { |
200 | _perChatHistory = v.toBool(); |
201 | } |
202 | |
203 | |
204 | void InputWidget::setMaxLines(const QVariant &v) |
205 | { |
206 | ui.inputEdit->setMaxHeight(v.toInt()); |
207 | } |
208 | |
209 | |
210 | void InputWidget::setScrollBarsEnabled(const QVariant &v) |
211 | { |
212 | ui.inputEdit->setScrollBarsEnabled(v.toBool()); |
213 | } |
214 | |
215 | |
216 | void InputWidget::setLineWrapEnabled(const QVariant &v) |
217 | { |
218 | ui.inputEdit->setLineWrapEnabled(v.toBool()); |
219 | } |
220 | |
221 | |
222 | void InputWidget::setMultiLineEnabled(const QVariant &v) |
223 | { |
224 | ui.inputEdit->setMode(v.toBool() ? MultiLineEdit::MultiLine : MultiLineEdit::SingleLine); |
225 | } |
226 | |
227 | |
228 | bool InputWidget::eventFilter(QObject *watched, QEvent *event) |
229 | { |
230 | if (event->type() != QEvent::KeyPress) |
231 | return false; |
232 | |
233 | QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); |
234 | |
235 | // keys from BufferView should be sent to (and focus) the input line |
236 | BufferView *view = qobject_cast<BufferView *>(watched); |
237 | if (view) { |
238 | if (keyEvent->text().length() == 1 && !(keyEvent->modifiers() & (Qt::ControlModifier ^ Qt::AltModifier))) { // normal key press |
239 | QChar c = keyEvent->text().at(0); |
240 | if (c.isLetterOrNumber() || c.isSpace() || c.isPunct() || c.isSymbol()) { |
241 | setFocus(); |
242 | QCoreApplication::sendEvent(inputLine(), keyEvent); |
243 | return true; |
244 | } |
245 | } |
246 | return false; |
247 | } |
248 | else if (watched == ui.inputEdit) { |
249 | if (keyEvent->matches(QKeySequence::Find)) { |
250 | QAction *act = GraphicalUi::actionCollection()->action("ToggleSearchBar" ); |
251 | if (act) { |
252 | act->toggle(); |
253 | return true; |
254 | } |
255 | } |
256 | return false; |
257 | } |
258 | return false; |
259 | } |
260 | |
261 | |
262 | void InputWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) |
263 | { |
264 | BufferId currentBufferId = current.data(NetworkModel::BufferIdRole).value<BufferId>(); |
265 | BufferId previousBufferId = previous.data(NetworkModel::BufferIdRole).value<BufferId>(); |
266 | |
267 | if (_perChatHistory) { |
268 | //backup |
269 | historyMap[previousBufferId].history = inputLine()->history(); |
270 | historyMap[previousBufferId].tempHistory = inputLine()->tempHistory(); |
271 | historyMap[previousBufferId].idx = inputLine()->idx(); |
272 | historyMap[previousBufferId].inputLine = inputLine()->html(); |
273 | |
274 | //restore |
275 | inputLine()->setHistory(historyMap[currentBufferId].history); |
276 | inputLine()->setTempHistory(historyMap[currentBufferId].tempHistory); |
277 | inputLine()->setIdx(historyMap[currentBufferId].idx); |
278 | inputLine()->setHtml(historyMap[currentBufferId].inputLine); |
279 | inputLine()->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); |
280 | |
281 | // FIXME this really should be in MultiLineEdit (and the const int on top removed) |
282 | QTextBlockFormat format = inputLine()->textCursor().blockFormat(); |
283 | format.setLeftMargin(leftMargin); // we want a little space between the frame and the contents |
284 | inputLine()->textCursor().setBlockFormat(format); |
285 | } |
286 | |
287 | NetworkId networkId = current.data(NetworkModel::NetworkIdRole).value<NetworkId>(); |
288 | if (networkId == _networkId) |
289 | return; |
290 | |
291 | setNetwork(networkId); |
292 | updateNickSelector(); |
293 | updateEnabledState(); |
294 | } |
295 | |
296 | |
297 | void InputWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) |
298 | { |
299 | QItemSelectionRange changedArea(topLeft, bottomRight); |
300 | if (changedArea.contains(selectionModel()->currentIndex())) { |
301 | updateEnabledState(); |
302 | |
303 | bool encrypted = false; |
304 | |
305 | IrcChannel *chan = qobject_cast<IrcChannel *>(Client::bufferModel()->data(selectionModel()->currentIndex(), NetworkModel::IrcChannelRole).value<QObject *>()); |
306 | if (chan) |
307 | encrypted = chan->encrypted(); |
308 | |
309 | IrcUser *user = qobject_cast<IrcUser *>(Client::bufferModel()->data(selectionModel()->currentIndex(), NetworkModel::IrcUserRole).value<QObject *>()); |
310 | if (user) |
311 | encrypted = user->encrypted(); |
312 | |
313 | if (encrypted) |
314 | ui.encryptionIconLabel->show(); |
315 | else |
316 | ui.encryptionIconLabel->hide(); |
317 | } |
318 | } |
319 | |
320 | |
321 | void InputWidget::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) |
322 | { |
323 | NetworkId networkId; |
324 | QModelIndex child; |
325 | for (int row = start; row <= end; row++) { |
326 | child = model()->index(row, 0, parent); |
327 | if (NetworkModel::NetworkItemType != child.data(NetworkModel::ItemTypeRole).toInt()) |
328 | continue; |
329 | networkId = child.data(NetworkModel::NetworkIdRole).value<NetworkId>(); |
330 | if (networkId == _networkId) { |
331 | setNetwork(0); |
332 | updateNickSelector(); |
333 | return; |
334 | } |
335 | } |
336 | } |
337 | |
338 | |
339 | void InputWidget::updateEnabledState() |
340 | { |
341 | // FIXME: Find a visualization for this that does not disable the widget! |
342 | // Disabling kills global action shortcuts, plus users sometimes need/want to enter text |
343 | // even in inactive channels. |
344 | #if 0 |
345 | QModelIndex currentIndex = selectionModel()->currentIndex(); |
346 | |
347 | const Network *net = Client::networkModel()->networkByIndex(currentIndex); |
348 | bool enabled = false; |
349 | if (net) { |
350 | // disable inputline if it's a channelbuffer we parted from or... |
351 | enabled = (currentIndex.data(NetworkModel::ItemActiveRole).value<bool>() || (currentIndex.data(NetworkModel::BufferTypeRole).toInt() != BufferInfo::ChannelBuffer)); |
352 | // ... if we're not connected to the network at all |
353 | enabled &= net->isConnected(); |
354 | } |
355 | |
356 | ui.inputEdit->setEnabled(enabled); |
357 | #endif |
358 | } |
359 | |
360 | |
361 | const Network *InputWidget::currentNetwork() const |
362 | { |
363 | return Client::network(_networkId); |
364 | } |
365 | |
366 | |
367 | BufferInfo InputWidget::currentBufferInfo() const |
368 | { |
369 | return selectionModel()->currentIndex().data(NetworkModel::BufferInfoRole).value<BufferInfo>(); |
370 | }; |
371 | |
372 | void InputWidget::setNetwork(NetworkId networkId) |
373 | { |
374 | if (_networkId == networkId) |
375 | return; |
376 | |
377 | const Network *previousNet = Client::network(_networkId); |
378 | if (previousNet) { |
379 | disconnect(previousNet, 0, this, 0); |
380 | if (previousNet->me()) |
381 | disconnect(previousNet->me(), 0, this, 0); |
382 | } |
383 | |
384 | _networkId = networkId; |
385 | |
386 | const Network *network = Client::network(networkId); |
387 | if (network) { |
388 | connect(network, SIGNAL(identitySet(IdentityId)), this, SLOT(setIdentity(IdentityId))); |
389 | connectMyIrcUser(); |
390 | setIdentity(network->identity()); |
391 | } |
392 | else { |
393 | setIdentity(0); |
394 | _networkId = 0; |
395 | } |
396 | } |
397 | |
398 | |
399 | void InputWidget::connectMyIrcUser() |
400 | { |
401 | const Network *network = currentNetwork(); |
402 | if (network->me()) { |
403 | connect(network->me(), SIGNAL(nickSet(const QString &)), this, SLOT(updateNickSelector())); |
404 | connect(network->me(), SIGNAL(userModesSet(QString)), this, SLOT(updateNickSelector())); |
405 | connect(network->me(), SIGNAL(userModesAdded(QString)), this, SLOT(updateNickSelector())); |
406 | connect(network->me(), SIGNAL(userModesRemoved(QString)), this, SLOT(updateNickSelector())); |
407 | connect(network->me(), SIGNAL(awaySet(bool)), this, SLOT(updateNickSelector())); |
408 | disconnect(network, SIGNAL(myNickSet(const QString &)), this, SLOT(connectMyIrcUser())); |
409 | updateNickSelector(); |
410 | } |
411 | else { |
412 | connect(network, SIGNAL(myNickSet(const QString &)), this, SLOT(connectMyIrcUser())); |
413 | } |
414 | } |
415 | |
416 | |
417 | void InputWidget::setIdentity(IdentityId identityId) |
418 | { |
419 | if (_identityId == identityId) |
420 | return; |
421 | |
422 | const Identity *previousIdentity = Client::identity(_identityId); |
423 | if (previousIdentity) |
424 | disconnect(previousIdentity, 0, this, 0); |
425 | |
426 | _identityId = identityId; |
427 | |
428 | const Identity *identity = Client::identity(identityId); |
429 | if (identity) { |
430 | connect(identity, SIGNAL(nicksSet(QStringList)), this, SLOT(updateNickSelector())); |
431 | } |
432 | else { |
433 | _identityId = 0; |
434 | } |
435 | updateNickSelector(); |
436 | } |
437 | |
438 | |
439 | void InputWidget::updateNickSelector() const |
440 | { |
441 | ui.ownNick->clear(); |
442 | |
443 | const Network *net = currentNetwork(); |
444 | if (!net) |
445 | return; |
446 | |
447 | const Identity *identity = Client::identity(net->identity()); |
448 | if (!identity) { |
449 | qWarning() << "InputWidget::updateNickSelector(): can't find Identity for Network" << net->networkId() << "IdentityId:" << net->identity(); |
450 | return; |
451 | } |
452 | |
453 | int nickIdx; |
454 | QStringList nicks = identity->nicks(); |
455 | if ((nickIdx = nicks.indexOf(net->myNick())) == -1) { |
456 | nicks.prepend(net->myNick()); |
457 | nickIdx = 0; |
458 | } |
459 | |
460 | if (nicks.isEmpty()) |
461 | return; |
462 | |
463 | IrcUser *me = net->me(); |
464 | if (me) { |
465 | nicks[nickIdx] = net->myNick(); |
466 | if (!me->userModes().isEmpty()) |
467 | nicks[nickIdx] += QString(" (+%1)" ).arg(me->userModes()); |
468 | } |
469 | |
470 | ui.ownNick->addItems(nicks); |
471 | |
472 | if (me && me->isAway()) |
473 | ui.ownNick->setItemData(nickIdx, SmallIcon("user-away" ), Qt::DecorationRole); |
474 | |
475 | ui.ownNick->setCurrentIndex(nickIdx); |
476 | } |
477 | |
478 | |
479 | void InputWidget::changeNick(const QString &newNick) const |
480 | { |
481 | const Network *net = currentNetwork(); |
482 | if (!net || net->isMyNick(newNick)) |
483 | return; |
484 | |
485 | // we reset the nick selecter as we have no confirmation yet, that this will succeed. |
486 | // if the action succeeds it will be properly updated anyways. |
487 | updateNickSelector(); |
488 | Client::userInput(BufferInfo::fakeStatusBuffer(net->networkId()), QString("/NICK %1" ).arg(newNick)); |
489 | } |
490 | |
491 | |
492 | void InputWidget::onTextEntered(const QString &text) |
493 | { |
494 | Client::userInput(currentBufferInfo(), text); |
495 | ui.boldButton->setChecked(false); |
496 | ui.underlineButton->setChecked(false); |
497 | ui.italicButton->setChecked(false); |
498 | |
499 | QTextCharFormat fmt; |
500 | fmt.setFontWeight(QFont::Normal); |
501 | fmt.setFontUnderline(false); |
502 | fmt.setFontItalic(false); |
503 | fmt.clearForeground(); |
504 | fmt.clearBackground(); |
505 | inputLine()->setCurrentCharFormat(fmt); |
506 | |
507 | #ifdef HAVE_KDE |
508 | // Set highlighter back to active in case it was deactivated by too many errors. |
509 | if (ui.inputEdit->highlighter()) |
510 | ui.inputEdit->highlighter()->setActive(true); |
511 | #endif |
512 | } |
513 | |
514 | |
515 | void InputWidget::mergeFormatOnSelection(const QTextCharFormat &format) |
516 | { |
517 | QTextCursor cursor = inputLine()->textCursor(); |
518 | cursor.mergeCharFormat(format); |
519 | inputLine()->mergeCurrentCharFormat(format); |
520 | } |
521 | |
522 | |
523 | void InputWidget::setFormatOnSelection(const QTextCharFormat &format) |
524 | { |
525 | QTextCursor cursor = inputLine()->textCursor(); |
526 | cursor.setCharFormat(format); |
527 | inputLine()->setCurrentCharFormat(format); |
528 | } |
529 | |
530 | |
531 | QTextCharFormat InputWidget::getFormatOfWordOrSelection() |
532 | { |
533 | QTextCursor cursor = inputLine()->textCursor(); |
534 | return cursor.charFormat(); |
535 | } |
536 | |
537 | |
538 | void InputWidget::currentCharFormatChanged(const QTextCharFormat &format) |
539 | { |
540 | fontChanged(format.font()); |
541 | } |
542 | |
543 | |
544 | void InputWidget::on_boldButton_clicked(bool checked) |
545 | { |
546 | QTextCharFormat fmt; |
547 | fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal); |
548 | mergeFormatOnSelection(fmt); |
549 | } |
550 | |
551 | |
552 | void InputWidget::on_underlineButton_clicked(bool checked) |
553 | { |
554 | QTextCharFormat fmt; |
555 | fmt.setFontUnderline(checked); |
556 | mergeFormatOnSelection(fmt); |
557 | } |
558 | |
559 | |
560 | void InputWidget::on_italicButton_clicked(bool checked) |
561 | { |
562 | QTextCharFormat fmt; |
563 | fmt.setFontItalic(checked); |
564 | mergeFormatOnSelection(fmt); |
565 | } |
566 | |
567 | |
568 | void InputWidget::fontChanged(const QFont &f) |
569 | { |
570 | ui.boldButton->setChecked(f.bold()); |
571 | ui.italicButton->setChecked(f.italic()); |
572 | ui.underlineButton->setChecked(f.underline()); |
573 | } |
574 | |
575 | |
576 | void InputWidget::colorChosen(QAction *action) |
577 | { |
578 | QTextCharFormat fmt; |
579 | QColor color; |
580 | if (action->data().value<QString>() == "" ) { |
581 | color = Qt::transparent; |
582 | fmt = getFormatOfWordOrSelection(); |
583 | fmt.clearForeground(); |
584 | setFormatOnSelection(fmt); |
585 | } |
586 | else { |
587 | color = QColor(inputLine()->rgbColorFromMirc(action->data().value<QString>())); |
588 | fmt.setForeground(color); |
589 | mergeFormatOnSelection(fmt); |
590 | } |
591 | ui.textcolorButton->setDefaultAction(action); |
592 | ui.textcolorButton->setIcon(createColorToolButtonIcon(SmallIcon("format-text-color" ), color)); |
593 | } |
594 | |
595 | |
596 | void InputWidget::colorHighlightChosen(QAction *action) |
597 | { |
598 | QTextCharFormat fmt; |
599 | QColor color; |
600 | if (action->data().value<QString>() == "" ) { |
601 | color = Qt::transparent; |
602 | fmt = getFormatOfWordOrSelection(); |
603 | fmt.clearBackground(); |
604 | setFormatOnSelection(fmt); |
605 | } |
606 | else { |
607 | color = QColor(inputLine()->rgbColorFromMirc(action->data().value<QString>())); |
608 | fmt.setBackground(color); |
609 | mergeFormatOnSelection(fmt); |
610 | } |
611 | ui.highlightcolorButton->setDefaultAction(action); |
612 | ui.highlightcolorButton->setIcon(createColorToolButtonIcon(SmallIcon("format-fill-color" ), color)); |
613 | } |
614 | |
615 | |
616 | void InputWidget::on_showStyleButton_toggled(bool checked) |
617 | { |
618 | ui.styleFrame->setVisible(checked); |
619 | if (checked) { |
620 | ui.showStyleButton->setArrowType(Qt::LeftArrow); |
621 | } |
622 | else { |
623 | ui.showStyleButton->setArrowType(Qt::RightArrow); |
624 | } |
625 | } |
626 | |
627 | |
628 | QIcon InputWidget::createColorToolButtonIcon(const QIcon &icon, const QColor &color) |
629 | { |
630 | QPixmap pixmap(16, 16); |
631 | pixmap.fill(Qt::transparent); |
632 | QPainter painter(&pixmap); |
633 | QPixmap image = icon.pixmap(16, 16); |
634 | QRect target(0, 0, 16, 14); |
635 | QRect source(0, 0, 16, 14); |
636 | painter.fillRect(QRect(0, 14, 16, 16), color); |
637 | painter.drawPixmap(target, image, source); |
638 | |
639 | return QIcon(pixmap); |
640 | } |
641 | |
642 | |
643 | // MOUSE WHEEL FILTER |
644 | MouseWheelFilter::MouseWheelFilter(QObject *parent) |
645 | : QObject(parent) |
646 | { |
647 | } |
648 | |
649 | |
650 | bool MouseWheelFilter::eventFilter(QObject *obj, QEvent *event) |
651 | { |
652 | if (event->type() != QEvent::Wheel) |
653 | return QObject::eventFilter(obj, event); |
654 | else |
655 | return true; |
656 | } |
657 | |