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 "client.h" |
22 | |
23 | #include "abstractmessageprocessor.h" |
24 | #include "abstractui.h" |
25 | #include "bufferinfo.h" |
26 | #include "buffermodel.h" |
27 | #include "buffersettings.h" |
28 | #include "buffersyncer.h" |
29 | #include "bufferviewconfig.h" |
30 | #include "bufferviewoverlay.h" |
31 | #include "clientaliasmanager.h" |
32 | #include "clientbacklogmanager.h" |
33 | #include "clientbufferviewmanager.h" |
34 | #include "clientirclisthelper.h" |
35 | #include "clientidentity.h" |
36 | #include "clientignorelistmanager.h" |
37 | #include "clienttransfermanager.h" |
38 | #include "clientuserinputhandler.h" |
39 | #include "coreaccountmodel.h" |
40 | #include "coreconnection.h" |
41 | #include "ircchannel.h" |
42 | #include "ircuser.h" |
43 | #include "message.h" |
44 | #include "messagemodel.h" |
45 | #include "network.h" |
46 | #include "networkconfig.h" |
47 | #include "networkmodel.h" |
48 | #include "quassel.h" |
49 | #include "signalproxy.h" |
50 | #include "util.h" |
51 | |
52 | #include <stdio.h> |
53 | #include <stdlib.h> |
54 | |
55 | QPointer<Client> Client::instanceptr = 0; |
56 | Quassel::Features Client::_coreFeatures = 0; |
57 | |
58 | /*** Initialization/destruction ***/ |
59 | |
60 | bool Client::instanceExists() |
61 | { |
62 | return instanceptr; |
63 | } |
64 | |
65 | |
66 | Client *Client::instance() |
67 | { |
68 | if (!instanceptr) |
69 | instanceptr = new Client(); |
70 | return instanceptr; |
71 | } |
72 | |
73 | |
74 | void Client::destroy() |
75 | { |
76 | if (instanceptr) { |
77 | delete instanceptr->mainUi(); |
78 | instanceptr->deleteLater(); |
79 | instanceptr = 0; |
80 | } |
81 | } |
82 | |
83 | |
84 | void Client::init(AbstractUi *ui) |
85 | { |
86 | instance()->_mainUi = ui; |
87 | instance()->init(); |
88 | } |
89 | |
90 | |
91 | Client::Client(QObject *parent) |
92 | : QObject(parent), |
93 | _signalProxy(new SignalProxy(SignalProxy::Client, this)), |
94 | _mainUi(0), |
95 | _networkModel(0), |
96 | _bufferModel(0), |
97 | _bufferSyncer(0), |
98 | _aliasManager(0), |
99 | _backlogManager(new ClientBacklogManager(this)), |
100 | _bufferViewManager(0), |
101 | _bufferViewOverlay(new BufferViewOverlay(this)), |
102 | _ircListHelper(new ClientIrcListHelper(this)), |
103 | _inputHandler(0), |
104 | _networkConfig(0), |
105 | _ignoreListManager(0), |
106 | _transferManager(0), |
107 | _messageModel(0), |
108 | _messageProcessor(0), |
109 | _coreAccountModel(new CoreAccountModel(this)), |
110 | _coreConnection(new CoreConnection(this)), |
111 | _connected(false), |
112 | _debugLog(&_debugLogBuffer) |
113 | { |
114 | _signalProxy->synchronize(_ircListHelper); |
115 | } |
116 | |
117 | |
118 | Client::~Client() |
119 | { |
120 | disconnectFromCore(); |
121 | } |
122 | |
123 | |
124 | void Client::init() |
125 | { |
126 | _networkModel = new NetworkModel(this); |
127 | |
128 | connect(this, SIGNAL(networkRemoved(NetworkId)), |
129 | _networkModel, SLOT(networkRemoved(NetworkId))); |
130 | |
131 | _bufferModel = new BufferModel(_networkModel); |
132 | _messageModel = mainUi()->createMessageModel(this); |
133 | _messageProcessor = mainUi()->createMessageProcessor(this); |
134 | _inputHandler = new ClientUserInputHandler(this); |
135 | |
136 | SignalProxy *p = signalProxy(); |
137 | |
138 | p->attachSlot(SIGNAL(displayMsg(const Message &)), this, SLOT(recvMessage(const Message &))); |
139 | p->attachSlot(SIGNAL(displayStatusMsg(QString, QString)), this, SLOT(recvStatusMsg(QString, QString))); |
140 | |
141 | p->attachSlot(SIGNAL(bufferInfoUpdated(BufferInfo)), _networkModel, SLOT(bufferUpdated(BufferInfo))); |
142 | p->attachSignal(inputHandler(), SIGNAL(sendInput(BufferInfo, QString))); |
143 | p->attachSignal(this, SIGNAL(requestNetworkStates())); |
144 | |
145 | p->attachSignal(this, SIGNAL(requestCreateIdentity(const Identity &, const QVariantMap &)), SIGNAL(createIdentity(const Identity &, const QVariantMap &))); |
146 | p->attachSignal(this, SIGNAL(requestRemoveIdentity(IdentityId)), SIGNAL(removeIdentity(IdentityId))); |
147 | p->attachSlot(SIGNAL(identityCreated(const Identity &)), this, SLOT(coreIdentityCreated(const Identity &))); |
148 | p->attachSlot(SIGNAL(identityRemoved(IdentityId)), this, SLOT(coreIdentityRemoved(IdentityId))); |
149 | |
150 | p->attachSignal(this, SIGNAL(requestCreateNetwork(const NetworkInfo &, const QStringList &)), SIGNAL(createNetwork(const NetworkInfo &, const QStringList &))); |
151 | p->attachSignal(this, SIGNAL(requestRemoveNetwork(NetworkId)), SIGNAL(removeNetwork(NetworkId))); |
152 | p->attachSlot(SIGNAL(networkCreated(NetworkId)), this, SLOT(coreNetworkCreated(NetworkId))); |
153 | p->attachSlot(SIGNAL(networkRemoved(NetworkId)), this, SLOT(coreNetworkRemoved(NetworkId))); |
154 | |
155 | //connect(mainUi(), SIGNAL(connectToCore(const QVariantMap &)), this, SLOT(connectToCore(const QVariantMap &))); |
156 | connect(mainUi(), SIGNAL(disconnectFromCore()), this, SLOT(disconnectFromCore())); |
157 | connect(this, SIGNAL(connected()), mainUi(), SLOT(connectedToCore())); |
158 | connect(this, SIGNAL(disconnected()), mainUi(), SLOT(disconnectedFromCore())); |
159 | |
160 | // attach backlog manager |
161 | p->synchronize(backlogManager()); |
162 | connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int))); |
163 | |
164 | coreAccountModel()->load(); |
165 | |
166 | connect(coreConnection(), SIGNAL(stateChanged(CoreConnection::ConnectionState)), SLOT(connectionStateChanged(CoreConnection::ConnectionState))); |
167 | coreConnection()->init(); |
168 | } |
169 | |
170 | |
171 | /*** public static methods ***/ |
172 | |
173 | AbstractUi *Client::mainUi() |
174 | { |
175 | return instance()->_mainUi; |
176 | } |
177 | |
178 | |
179 | void Client::setCoreFeatures(Quassel::Features features) |
180 | { |
181 | _coreFeatures = features; |
182 | } |
183 | |
184 | |
185 | bool Client::isConnected() |
186 | { |
187 | return instance()->_connected; |
188 | } |
189 | |
190 | |
191 | bool Client::internalCore() |
192 | { |
193 | return currentCoreAccount().isInternal(); |
194 | } |
195 | |
196 | |
197 | /*** Network handling ***/ |
198 | |
199 | QList<NetworkId> Client::networkIds() |
200 | { |
201 | return instance()->_networks.keys(); |
202 | } |
203 | |
204 | |
205 | const Network *Client::network(NetworkId networkid) |
206 | { |
207 | if (instance()->_networks.contains(networkid)) return instance()->_networks[networkid]; |
208 | else return 0; |
209 | } |
210 | |
211 | |
212 | void Client::createNetwork(const NetworkInfo &info, const QStringList &persistentChannels) |
213 | { |
214 | emit instance()->requestCreateNetwork(info, persistentChannels); |
215 | } |
216 | |
217 | |
218 | void Client::removeNetwork(NetworkId id) |
219 | { |
220 | emit instance()->requestRemoveNetwork(id); |
221 | } |
222 | |
223 | |
224 | void Client::updateNetwork(const NetworkInfo &info) |
225 | { |
226 | Network *netptr = instance()->_networks.value(info.networkId, 0); |
227 | if (!netptr) { |
228 | qWarning() << "Update for unknown network requested:" << info; |
229 | return; |
230 | } |
231 | netptr->requestSetNetworkInfo(info); |
232 | } |
233 | |
234 | |
235 | void Client::addNetwork(Network *net) |
236 | { |
237 | net->setProxy(signalProxy()); |
238 | signalProxy()->synchronize(net); |
239 | networkModel()->attachNetwork(net); |
240 | connect(net, SIGNAL(destroyed()), instance(), SLOT(networkDestroyed())); |
241 | instance()->_networks[net->networkId()] = net; |
242 | emit instance()->networkCreated(net->networkId()); |
243 | } |
244 | |
245 | |
246 | void Client::coreNetworkCreated(NetworkId id) |
247 | { |
248 | if (_networks.contains(id)) { |
249 | qWarning() << "Creation of already existing network requested!" ; |
250 | return; |
251 | } |
252 | Network *net = new Network(id, this); |
253 | addNetwork(net); |
254 | } |
255 | |
256 | |
257 | void Client::coreNetworkRemoved(NetworkId id) |
258 | { |
259 | if (!_networks.contains(id)) |
260 | return; |
261 | Network *net = _networks.take(id); |
262 | emit networkRemoved(net->networkId()); |
263 | net->deleteLater(); |
264 | } |
265 | |
266 | |
267 | /*** Identity handling ***/ |
268 | |
269 | QList<IdentityId> Client::identityIds() |
270 | { |
271 | return instance()->_identities.keys(); |
272 | } |
273 | |
274 | |
275 | const Identity *Client::identity(IdentityId id) |
276 | { |
277 | if (instance()->_identities.contains(id)) return instance()->_identities[id]; |
278 | else return 0; |
279 | } |
280 | |
281 | |
282 | void Client::createIdentity(const CertIdentity &id) |
283 | { |
284 | QVariantMap additional; |
285 | #ifdef HAVE_SSL |
286 | additional["KeyPem" ] = id.sslKey().toPem(); |
287 | additional["CertPem" ] = id.sslCert().toPem(); |
288 | #endif |
289 | emit instance()->requestCreateIdentity(id, additional); |
290 | } |
291 | |
292 | |
293 | void Client::updateIdentity(IdentityId id, const QVariantMap &ser) |
294 | { |
295 | Identity *idptr = instance()->_identities.value(id, 0); |
296 | if (!idptr) { |
297 | qWarning() << "Update for unknown identity requested:" << id; |
298 | return; |
299 | } |
300 | idptr->requestUpdate(ser); |
301 | } |
302 | |
303 | |
304 | void Client::removeIdentity(IdentityId id) |
305 | { |
306 | emit instance()->requestRemoveIdentity(id); |
307 | } |
308 | |
309 | |
310 | void Client::coreIdentityCreated(const Identity &other) |
311 | { |
312 | if (!_identities.contains(other.id())) { |
313 | Identity *identity = new Identity(other, this); |
314 | _identities[other.id()] = identity; |
315 | identity->setInitialized(); |
316 | signalProxy()->synchronize(identity); |
317 | emit identityCreated(other.id()); |
318 | } |
319 | else { |
320 | qWarning() << tr("Identity already exists in client!" ); |
321 | } |
322 | } |
323 | |
324 | |
325 | void Client::coreIdentityRemoved(IdentityId id) |
326 | { |
327 | if (_identities.contains(id)) { |
328 | emit identityRemoved(id); |
329 | Identity *i = _identities.take(id); |
330 | i->deleteLater(); |
331 | } |
332 | } |
333 | |
334 | |
335 | /*** User input handling ***/ |
336 | |
337 | void Client::userInput(const BufferInfo &bufferInfo, const QString &message) |
338 | { |
339 | // we need to make sure that AliasManager is ready before processing input |
340 | if (aliasManager() && aliasManager()->isInitialized()) |
341 | inputHandler()->handleUserInput(bufferInfo, message); |
342 | else |
343 | instance()->_userInputBuffer.append(qMakePair(bufferInfo, message)); |
344 | } |
345 | |
346 | |
347 | void Client::sendBufferedUserInput() |
348 | { |
349 | for (int i = 0; i < _userInputBuffer.count(); i++) |
350 | userInput(_userInputBuffer.at(i).first, _userInputBuffer.at(i).second); |
351 | |
352 | _userInputBuffer.clear(); |
353 | } |
354 | |
355 | |
356 | /*** core connection stuff ***/ |
357 | |
358 | void Client::connectionStateChanged(CoreConnection::ConnectionState state) |
359 | { |
360 | switch (state) { |
361 | case CoreConnection::Disconnected: |
362 | setDisconnectedFromCore(); |
363 | break; |
364 | case CoreConnection::Synchronized: |
365 | setSyncedToCore(); |
366 | break; |
367 | default: |
368 | break; |
369 | } |
370 | } |
371 | |
372 | |
373 | void Client::setSyncedToCore() |
374 | { |
375 | // create buffersyncer |
376 | Q_ASSERT(!_bufferSyncer); |
377 | _bufferSyncer = new BufferSyncer(this); |
378 | connect(bufferSyncer(), SIGNAL(lastSeenMsgSet(BufferId, MsgId)), _networkModel, SLOT(setLastSeenMsgId(BufferId, MsgId))); |
379 | connect(bufferSyncer(), SIGNAL(markerLineSet(BufferId, MsgId)), _networkModel, SLOT(setMarkerLineMsgId(BufferId, MsgId))); |
380 | connect(bufferSyncer(), SIGNAL(bufferRemoved(BufferId)), this, SLOT(bufferRemoved(BufferId))); |
381 | connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString))); |
382 | connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); |
383 | connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); |
384 | connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId))); |
385 | connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); |
386 | signalProxy()->synchronize(bufferSyncer()); |
387 | |
388 | // create a new BufferViewManager |
389 | Q_ASSERT(!_bufferViewManager); |
390 | _bufferViewManager = new ClientBufferViewManager(signalProxy(), this); |
391 | connect(_bufferViewManager, SIGNAL(initDone()), _bufferViewOverlay, SLOT(restore())); |
392 | |
393 | // create AliasManager |
394 | Q_ASSERT(!_aliasManager); |
395 | _aliasManager = new ClientAliasManager(this); |
396 | connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput())); |
397 | signalProxy()->synchronize(aliasManager()); |
398 | |
399 | // create NetworkConfig |
400 | Q_ASSERT(!_networkConfig); |
401 | _networkConfig = new NetworkConfig("GlobalNetworkConfig" , this); |
402 | signalProxy()->synchronize(networkConfig()); |
403 | |
404 | // create IgnoreListManager |
405 | Q_ASSERT(!_ignoreListManager); |
406 | _ignoreListManager = new ClientIgnoreListManager(this); |
407 | signalProxy()->synchronize(ignoreListManager()); |
408 | |
409 | Q_ASSERT(!_transferManager); |
410 | _transferManager = new ClientTransferManager(this); |
411 | signalProxy()->synchronize(transferManager()); |
412 | |
413 | // trigger backlog request once all active bufferviews are initialized |
414 | connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); |
415 | |
416 | _connected = true; |
417 | emit connected(); |
418 | emit coreConnectionStateChanged(true); |
419 | } |
420 | |
421 | |
422 | void Client::requestInitialBacklog() |
423 | { |
424 | // usually it _should_ take longer until the bufferViews are initialized, so that's what |
425 | // triggers this slot. But we have to make sure that we know all buffers yet. |
426 | // so we check the BufferSyncer and in case it wasn't initialized we wait for that instead |
427 | if (!bufferSyncer()->isInitialized()) { |
428 | disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); |
429 | connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); |
430 | return; |
431 | } |
432 | disconnect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); |
433 | disconnect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); |
434 | |
435 | _backlogManager->requestInitialBacklog(); |
436 | } |
437 | |
438 | |
439 | void Client::disconnectFromCore() |
440 | { |
441 | if (!coreConnection()->isConnected()) |
442 | return; |
443 | |
444 | coreConnection()->disconnectFromCore(); |
445 | } |
446 | |
447 | |
448 | void Client::setDisconnectedFromCore() |
449 | { |
450 | _connected = false; |
451 | _coreFeatures = 0; |
452 | |
453 | emit disconnected(); |
454 | emit coreConnectionStateChanged(false); |
455 | |
456 | backlogManager()->reset(); |
457 | messageProcessor()->reset(); |
458 | |
459 | // Clear internal data. Hopefully nothing relies on it at this point. |
460 | |
461 | if (_bufferSyncer) { |
462 | _bufferSyncer->deleteLater(); |
463 | _bufferSyncer = 0; |
464 | } |
465 | |
466 | if (_bufferViewManager) { |
467 | _bufferViewManager->deleteLater(); |
468 | _bufferViewManager = 0; |
469 | } |
470 | |
471 | _bufferViewOverlay->reset(); |
472 | |
473 | if (_aliasManager) { |
474 | _aliasManager->deleteLater(); |
475 | _aliasManager = 0; |
476 | } |
477 | |
478 | if (_ignoreListManager) { |
479 | _ignoreListManager->deleteLater(); |
480 | _ignoreListManager = 0; |
481 | } |
482 | |
483 | if (_transferManager) { |
484 | _transferManager->deleteLater(); |
485 | _transferManager = 0; |
486 | } |
487 | |
488 | // we probably don't want to save pending input for reconnect |
489 | _userInputBuffer.clear(); |
490 | |
491 | _messageModel->clear(); |
492 | _networkModel->clear(); |
493 | |
494 | QHash<NetworkId, Network *>::iterator netIter = _networks.begin(); |
495 | while (netIter != _networks.end()) { |
496 | Network *net = netIter.value(); |
497 | emit networkRemoved(net->networkId()); |
498 | disconnect(net, SIGNAL(destroyed()), this, 0); |
499 | netIter = _networks.erase(netIter); |
500 | net->deleteLater(); |
501 | } |
502 | Q_ASSERT(_networks.isEmpty()); |
503 | |
504 | QHash<IdentityId, Identity *>::iterator idIter = _identities.begin(); |
505 | while (idIter != _identities.end()) { |
506 | emit identityRemoved(idIter.key()); |
507 | Identity *id = idIter.value(); |
508 | idIter = _identities.erase(idIter); |
509 | id->deleteLater(); |
510 | } |
511 | Q_ASSERT(_identities.isEmpty()); |
512 | |
513 | if (_networkConfig) { |
514 | _networkConfig->deleteLater(); |
515 | _networkConfig = 0; |
516 | } |
517 | } |
518 | |
519 | |
520 | /*** ***/ |
521 | |
522 | void Client::networkDestroyed() |
523 | { |
524 | Network *net = static_cast<Network *>(sender()); |
525 | QHash<NetworkId, Network *>::iterator netIter = _networks.begin(); |
526 | while (netIter != _networks.end()) { |
527 | if (*netIter == net) { |
528 | netIter = _networks.erase(netIter); |
529 | break; |
530 | } |
531 | else { |
532 | netIter++; |
533 | } |
534 | } |
535 | } |
536 | |
537 | |
538 | // Hmm... we never used this... |
539 | void Client::recvStatusMsg(QString /*net*/, QString /*msg*/) |
540 | { |
541 | //recvMessage(net, Message::server("", QString("[STATUS] %1").arg(msg))); |
542 | } |
543 | |
544 | |
545 | void Client::recvMessage(const Message &msg) |
546 | { |
547 | Message msg_ = msg; |
548 | messageProcessor()->process(msg_); |
549 | } |
550 | |
551 | |
552 | void Client::setBufferLastSeenMsg(BufferId id, const MsgId &msgId) |
553 | { |
554 | if (bufferSyncer()) |
555 | bufferSyncer()->requestSetLastSeenMsg(id, msgId); |
556 | } |
557 | |
558 | |
559 | void Client::setMarkerLine(BufferId id, const MsgId &msgId) |
560 | { |
561 | if (bufferSyncer()) |
562 | bufferSyncer()->requestSetMarkerLine(id, msgId); |
563 | } |
564 | |
565 | |
566 | MsgId Client::markerLine(BufferId id) |
567 | { |
568 | if (id.isValid() && networkModel()) |
569 | return networkModel()->markerLineMsgId(id); |
570 | return MsgId(); |
571 | } |
572 | |
573 | |
574 | void Client::removeBuffer(BufferId id) |
575 | { |
576 | if (!bufferSyncer()) return; |
577 | bufferSyncer()->requestRemoveBuffer(id); |
578 | } |
579 | |
580 | |
581 | void Client::renameBuffer(BufferId bufferId, const QString &newName) |
582 | { |
583 | if (!bufferSyncer()) |
584 | return; |
585 | bufferSyncer()->requestRenameBuffer(bufferId, newName); |
586 | } |
587 | |
588 | |
589 | void Client::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) |
590 | { |
591 | if (!bufferSyncer()) |
592 | return; |
593 | bufferSyncer()->requestMergeBuffersPermanently(bufferId1, bufferId2); |
594 | } |
595 | |
596 | |
597 | void Client::purgeKnownBufferIds() |
598 | { |
599 | if (!bufferSyncer()) |
600 | return; |
601 | bufferSyncer()->requestPurgeBufferIds(); |
602 | } |
603 | |
604 | |
605 | void Client::bufferRemoved(BufferId bufferId) |
606 | { |
607 | // select a sane buffer (status buffer) |
608 | /* we have to manually select a buffer because otherwise inconsitent changes |
609 | * to the model might occur: |
610 | * the result of a buffer removal triggers a change in the selection model. |
611 | * the newly selected buffer might be a channel that hasn't been selected yet |
612 | * and a new nickview would be created (which never heard of the "rowsAboutToBeRemoved"). |
613 | * this new view (and/or) its sort filter will then only receive a "rowsRemoved" signal. |
614 | */ |
615 | QModelIndex current = bufferModel()->currentIndex(); |
616 | if (current.data(NetworkModel::BufferIdRole).value<BufferId>() == bufferId) { |
617 | bufferModel()->setCurrentIndex(current.sibling(0, 0)); |
618 | } |
619 | |
620 | // and remove it from the model |
621 | networkModel()->removeBuffer(bufferId); |
622 | } |
623 | |
624 | |
625 | void Client::bufferRenamed(BufferId bufferId, const QString &newName) |
626 | { |
627 | QModelIndex bufferIndex = networkModel()->bufferIndex(bufferId); |
628 | if (bufferIndex.isValid()) { |
629 | networkModel()->setData(bufferIndex, newName, Qt::DisplayRole); |
630 | } |
631 | } |
632 | |
633 | |
634 | void Client::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) |
635 | { |
636 | QModelIndex idx = networkModel()->bufferIndex(bufferId1); |
637 | bufferModel()->setCurrentIndex(bufferModel()->mapFromSource(idx)); |
638 | networkModel()->removeBuffer(bufferId2); |
639 | } |
640 | |
641 | |
642 | void Client::markBufferAsRead(BufferId id) |
643 | { |
644 | if (bufferSyncer() && id.isValid()) |
645 | bufferSyncer()->requestMarkBufferAsRead(id); |
646 | } |
647 | |
648 | |
649 | #if QT_VERSION < 0x050000 |
650 | void Client::logMessage(QtMsgType type, const char *msg) |
651 | { |
652 | fprintf(stderr, "%s\n" , msg); |
653 | fflush(stderr); |
654 | if (type == QtFatalMsg) { |
655 | Quassel::logFatalMessage(msg); |
656 | } |
657 | else { |
658 | QString msgString = QString("%1\n" ).arg(msg); |
659 | |
660 | //Check to see if there is an instance around, else we risk recursions |
661 | //when calling instance() and creating new ones. |
662 | if (!instanceExists()) |
663 | return; |
664 | |
665 | instance()->_debugLog << msgString; |
666 | emit instance()->logUpdated(msgString); |
667 | } |
668 | } |
669 | #else |
670 | void Client::logMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) |
671 | { |
672 | Q_UNUSED(context); |
673 | |
674 | fprintf(stderr, "%s\n" , msg.toLocal8Bit().constData()); |
675 | fflush(stderr); |
676 | if (type == QtFatalMsg) { |
677 | Quassel::logFatalMessage(msg.toLocal8Bit().constData()); |
678 | } |
679 | else { |
680 | QString msgString = QString("%1\n" ).arg(msg); |
681 | |
682 | //Check to see if there is an instance around, else we risk recursions |
683 | //when calling instance() and creating new ones. |
684 | if (!instanceExists()) |
685 | return; |
686 | |
687 | instance()->_debugLog << msgString; |
688 | emit instance()->logUpdated(msgString); |
689 | } |
690 | } |
691 | #endif |
692 | |