From 3c2914faeb01f3bc32e29f40179ae88040fbcf59 Mon Sep 17 00:00:00 2001 From: Marcus Eggenberger Date: Mon, 29 Dec 2008 18:58:04 +0100 Subject: [PATCH 1/1] introducing query merging (per drag & drop). needs a core update --- src/client/client.cpp | 14 +++ src/client/client.h | 2 + src/client/messagefilter.cpp | 2 + src/client/messagemodel.cpp | 11 +- src/client/messagemodel.h | 2 + src/client/networkmodel.cpp | 43 ------- src/client/networkmodel.h | 1 - src/common/buffersyncer.cpp | 14 ++- src/common/buffersyncer.h | 10 ++ .../SQL/SQLite/13/update_backlog_bufferid.sql | 3 + src/core/core.cpp | 2 +- src/core/core.h | 13 ++ src/core/corebuffersyncer.cpp | 112 ++++++++++++++++++ src/core/corebuffersyncer.h | 54 +++++++++ src/core/coresession.cpp | 4 +- src/core/sql.qrc | 1 + src/core/sqlitestorage.cpp | 21 ++++ src/core/sqlitestorage.h | 1 + src/core/storage.h | 11 +- src/uisupport/bufferview.cpp | 31 +++++ src/uisupport/bufferview.h | 1 + 21 files changed, 299 insertions(+), 54 deletions(-) create mode 100644 src/core/SQL/SQLite/13/update_backlog_bufferid.sql create mode 100644 src/core/corebuffersyncer.cpp create mode 100644 src/core/corebuffersyncer.h diff --git a/src/client/client.cpp b/src/client/client.cpp index 9956cd2b..52a2d13f 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -286,6 +286,8 @@ void Client::setSyncedToCore() { connect(bufferSyncer(), SIGNAL(lastSeenMsgSet(BufferId, MsgId)), _networkModel, SLOT(setLastSeenMsgId(BufferId, MsgId))); connect(bufferSyncer(), SIGNAL(bufferRemoved(BufferId)), this, SLOT(bufferRemoved(BufferId))); connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString))); + connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); + connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); connect(bufferSyncer(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog())); connect(networkModel(), SIGNAL(setLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); signalProxy()->synchronize(bufferSyncer()); @@ -404,6 +406,12 @@ void Client::renameBuffer(BufferId bufferId, const QString &newName) { bufferSyncer()->requestRenameBuffer(bufferId, newName); } +void Client::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) { + if(!bufferSyncer()) + return; + bufferSyncer()->requestMergeBuffersPermanently(bufferId1, bufferId2); +} + void Client::bufferRemoved(BufferId bufferId) { // select a sane buffer (status buffer) /* we have to manually select a buffer because otherwise inconsitent changes @@ -429,6 +437,12 @@ void Client::bufferRenamed(BufferId bufferId, const QString &newName) { } } +void Client::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) { + QModelIndex idx = networkModel()->bufferIndex(bufferId1); + bufferModel()->setCurrentIndex(bufferModel()->mapFromSource(idx)); + networkModel()->removeBuffer(bufferId2); +} + void Client::logMessage(QtMsgType type, const char *msg) { fprintf(stderr, "%s\n", msg); fflush(stderr); diff --git a/src/client/client.h b/src/client/client.h index ac3663dd..362b5233 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -114,6 +114,7 @@ public: static void setBufferLastSeenMsg(BufferId id, const MsgId &msgId); // this is synced to core and other clients static void removeBuffer(BufferId id); static void renameBuffer(BufferId bufferId, const QString &newName); + static void mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2); static void logMessage(QtMsgType type, const char *msg); static inline const QString &debugLog() { return instance()->_debugLogBuffer; } @@ -164,6 +165,7 @@ public slots: void bufferRemoved(BufferId bufferId); void bufferRenamed(BufferId bufferId, const QString &newName); + void buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2); private slots: void disconnectedFromCore(); diff --git a/src/client/messagefilter.cpp b/src/client/messagefilter.cpp index f7a1d810..cc2ec8b6 100644 --- a/src/client/messagefilter.cpp +++ b/src/client/messagefilter.cpp @@ -44,6 +44,8 @@ MessageFilter::MessageFilter(MessageModel *source, const QList &buffer } void MessageFilter::init() { + setDynamicSortFilter(true); + BufferSettings defaultSettings; _messageTypeFilter = defaultSettings.messageFilter(); defaultSettings.notify("MessageTypeFilter", this, SLOT(messageTypeFilterChanged())); diff --git a/src/client/messagemodel.cpp b/src/client/messagemodel.cpp index 1ece82fc..945ac7da 100644 --- a/src/client/messagemodel.cpp +++ b/src/client/messagemodel.cpp @@ -385,6 +385,16 @@ void MessageModel::messagesReceived(BufferId bufferId, int count) { _messagesWaiting.remove(bufferId); } +void MessageModel::buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2) { + for(int i = 0; i < _messageList.count(); i++) { + if(_messageList[i]->bufferId() == bufferId2) { + _messageList[i]->setBufferId(bufferId1); + QModelIndex idx = index(i, 0); + emit dataChanged(idx, idx); + } + } +} + // ======================================== // MessageModelItem // ======================================== @@ -426,7 +436,6 @@ bool MessageModelItem::setData(int column, const QVariant &value, int role) { } } - // Stuff for later bool MessageModelItem::lessThan(const MessageModelItem *m1, const MessageModelItem *m2){ return (*m1) < (*m2); diff --git a/src/client/messagemodel.h b/src/client/messagemodel.h index c7c975d8..b65fbbfa 100644 --- a/src/client/messagemodel.h +++ b/src/client/messagemodel.h @@ -72,6 +72,7 @@ public: public slots: void requestBacklog(BufferId bufferId); void messagesReceived(BufferId bufferId, int count); + void buffersPermanentlyMerged(BufferId bufferId1, BufferId bufferId2); protected: virtual MessageModelItem *createMessageModelItem(const Message &) = 0; @@ -111,6 +112,7 @@ public: inline const QDateTime &timeStamp() const { return _timestamp; } inline MsgId msgId() const { return _msgId; } inline BufferId bufferId() const { return _bufferId; } + inline void setBufferId(BufferId bufferId) { _bufferId = bufferId; } inline Message::Type msgType() const { return _type; } inline Message::Flags msgFlags() const { return _flags; } diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index 7d644422..962c9f8f 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -891,49 +891,6 @@ QMimeData *NetworkModel::mimeData(const QModelIndexList &indexes) const { return mimeData; } -bool NetworkModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { - Q_UNUSED(action) - Q_UNUSED(row) - Q_UNUSED(column) - - if(!mimeContainsBufferList(data)) - return false; - - // target must be a query - BufferInfo::Type targetType = (BufferInfo::Type)parent.data(NetworkModel::BufferTypeRole).toInt(); - if(targetType != BufferInfo::QueryBuffer) - return false; - - QList< QPair > bufferList = mimeDataToBufferList(data); - - // exactly one buffer has to be dropped - if(bufferList.count() != 1) - return false; - - NetworkId netId = bufferList.first().first; - BufferId bufferId = bufferList.first().second; - - // no self merges (would kill us) - if(bufferId == parent.data(BufferIdRole).value()) - return false; - - NetworkItem *netItem = findNetworkItem(netId); - Q_ASSERT(netItem); - - BufferItem *bufferItem = netItem->findBufferItem(bufferId); - Q_ASSERT(bufferItem); - - // source must be a query too - if(bufferItem->bufferType() != BufferInfo::QueryBuffer) - return false; - - // TODO: warn user about buffermerge! - qDebug() << "merging" << bufferId << parent.data(BufferIdRole).value(); - removeRow(parent.row(), parent.parent()); - - return true; -} - void NetworkModel::attachNetwork(Network *net) { NetworkItem *netItem = networkItem(net->networkId()); netItem->attachNetwork(net); diff --git a/src/client/networkmodel.h b/src/client/networkmodel.h index e765252b..7412d135 100644 --- a/src/client/networkmodel.h +++ b/src/client/networkmodel.h @@ -277,7 +277,6 @@ public: virtual QStringList mimeTypes() const; virtual QMimeData *mimeData(const QModelIndexList &) const; - virtual bool dropMimeData(const QMimeData *, Qt::DropAction, int, int, const QModelIndex &); void attachNetwork(Network *network); diff --git a/src/common/buffersyncer.cpp b/src/common/buffersyncer.cpp index 816227fa..c6fa1e79 100644 --- a/src/common/buffersyncer.cpp +++ b/src/common/buffersyncer.cpp @@ -65,12 +65,14 @@ void BufferSyncer::initSetLastSeenMsg(const QVariantList &list) { } void BufferSyncer::removeBuffer(BufferId buffer) { - if(_lastSeenMsg.contains(buffer)) { + if(_lastSeenMsg.contains(buffer)) _lastSeenMsg.remove(buffer); - emit bufferRemoved(buffer); - } + emit bufferRemoved(buffer); } -// void BufferSyncer::renameBuffer(BufferId buffer, QString newName) { -// emit bufferRenamed(buffer, newName); -// } + +void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { + if(_lastSeenMsg.contains(buffer2)) + _lastSeenMsg.remove(buffer2); + emit buffersPermanentlyMerged(buffer1, buffer2); +} diff --git a/src/common/buffersyncer.h b/src/common/buffersyncer.h index 92ca54d5..f57caaec 100644 --- a/src/common/buffersyncer.h +++ b/src/common/buffersyncer.h @@ -38,19 +38,29 @@ public slots: void initSetLastSeenMsg(const QVariantList &); virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { emit setLastSeenMsgRequested(buffer, msgId); } + virtual inline void requestRemoveBuffer(BufferId buffer) { emit removeBufferRequested(buffer); } virtual void removeBuffer(BufferId buffer); + virtual inline void requestRenameBuffer(BufferId buffer, QString newName) { emit renameBufferRequested(buffer, newName); } virtual inline void renameBuffer(BufferId buffer, QString newName) { emit bufferRenamed(buffer, newName); } + virtual inline void requestMergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { emit mergeBuffersPermanentlyRequested(buffer1, buffer2); } + virtual void mergeBuffersPermanently(BufferId buffer1, BufferId buffer2); + signals: void lastSeenMsgSet(BufferId buffer, const MsgId &msgId); void setLastSeenMsgRequested(BufferId buffer, const MsgId &msgId); + void removeBufferRequested(BufferId buffer); void bufferRemoved(BufferId buffer); + void renameBufferRequested(BufferId buffer, QString newName); void bufferRenamed(BufferId buffer, QString newName); + void mergeBuffersPermanentlyRequested(BufferId buffer1, BufferId buffer2); + void buffersPermanentlyMerged(BufferId buffer1, BufferId buffer2); + protected slots: bool setLastSeenMsg(BufferId buffer, const MsgId &msgId); diff --git a/src/core/SQL/SQLite/13/update_backlog_bufferid.sql b/src/core/SQL/SQLite/13/update_backlog_bufferid.sql new file mode 100644 index 00000000..b490b29f --- /dev/null +++ b/src/core/SQL/SQLite/13/update_backlog_bufferid.sql @@ -0,0 +1,3 @@ +UPDATE backlog +SET bufferid = :newbufferid +WHERE bufferid = :oldbufferid diff --git a/src/core/core.cpp b/src/core/core.cpp index 830a79b1..233157bc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -63,7 +63,7 @@ Core::Core() : storage(0) { exit(1); // TODO make this less brutal (especially for mono client -> popup) } connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage())); - _storageSyncTimer.start(10 * 60 * 1000); // in msecs + _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes } void Core::init() { diff --git a/src/core/core.h b/src/core/core.h index 6ddb6e86..8945b0ea 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -300,6 +300,17 @@ class Core : public QObject { return instance()->storage->renameBuffer(user, bufferId, newName); } + //! Merge the content of two Buffers permanently. This cannot be reversed! + /** \note This method is threadsafe. + * \param user The id of the buffer owner + * \param bufferId1 The bufferId of the remaining buffer + * \param bufferId2 The buffer that is about to be removed + * \return true if successfulln + */ + static inline bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) { + return instance()->storage->mergeBuffersPermanently(user, bufferId1, bufferId2); + } + //! Update the LastSeenDate for a Buffer /** This Method is used to make the LastSeenDate of a Buffer persistent * \note This method is threadsafe. @@ -324,6 +335,8 @@ class Core : public QObject { const QDateTime &startTime() const { return _startTime; } + static inline QTimer &syncTimer() { return instance()->_storageSyncTimer; } + public slots: //! Make storage data persistent /** \note This method is threadsafe. diff --git a/src/core/corebuffersyncer.cpp b/src/core/corebuffersyncer.cpp new file mode 100644 index 00000000..f218508f --- /dev/null +++ b/src/core/corebuffersyncer.cpp @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel Project * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "corebuffersyncer.h" + +#include "core.h" +#include "coresession.h" +#include "corenetwork.h" +#include "ircchannel.h" + +CoreBufferSyncer::CoreBufferSyncer(CoreSession *parent) + : BufferSyncer(parent), + _coreSession(parent) +{ +} + +void CoreBufferSyncer::requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { + if(setLastSeenMsg(buffer, msgId)) + dirtyBuffers << buffer; +} + +void CoreBufferSyncer::storeDirtyIds() { + UserId userId = _coreSession->user(); + MsgId msgId; + foreach(BufferId bufferId, dirtyBuffers) { + msgId = lastSeenMsg(bufferId); + if(msgId.isValid()) + Core::setBufferLastSeenMsg(userId, bufferId, msgId); + } + dirtyBuffers.clear(); +} + +void CoreBufferSyncer::removeBuffer(BufferId bufferId) { + BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId); + if(!bufferInfo.isValid()) { + qWarning() << "CoreBufferSyncer::removeBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user(); + return; + } + + if(bufferInfo.type() == BufferInfo::StatusBuffer) { + qWarning() << "CoreBufferSyncer::removeBuffer(): Status Buffers cannot be removed!"; + return; + } + + if(bufferInfo.type() == BufferInfo::ChannelBuffer) { + CoreNetwork *net = _coreSession->network(bufferInfo.networkId()); + if(!net) { + qWarning() << "CoreBufferSyncer::removeBuffer(): Received BufferInfo with unknown networkId!"; + return; + } + IrcChannel *chan = net->ircChannel(bufferInfo.bufferName()); + if(chan) { + qWarning() << "CoreBufferSyncer::removeBuffer(): Unable to remove Buffer for joined Channel:" << bufferInfo.bufferName(); + return; + } + } + if(Core::removeBuffer(_coreSession->user(), bufferId)) + BufferSyncer::removeBuffer(bufferId); +} + +void CoreBufferSyncer::renameBuffer(BufferId bufferId, QString newName) { + BufferInfo bufferInfo = Core::getBufferInfo(_coreSession->user(), bufferId); + if(!bufferInfo.isValid()) { + qWarning() << "CoreBufferSyncer::renameBuffer(): invalid BufferId:" << bufferId << "for User:" << _coreSession->user(); + return; + } + + if(bufferInfo.type() != BufferInfo::QueryBuffer) { + qWarning() << "CoreBufferSyncer::renameBuffer(): only QueryBuffers can be renamed" << bufferId; + return; + } + + if(Core::renameBuffer(_coreSession->user(), bufferId, newName)) + BufferSyncer::renameBuffer(bufferId, newName); +} + +void CoreBufferSyncer::mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2) { + BufferInfo bufferInfo1 = Core::getBufferInfo(_coreSession->user(), bufferId1); + BufferInfo bufferInfo2 = Core::getBufferInfo(_coreSession->user(), bufferId2); + qDebug() << Q_FUNC_INFO << bufferInfo1 << bufferInfo2; + if(!bufferInfo1.isValid() || !bufferInfo2.isValid()) { + qWarning() << "CoreBufferSyncer::mergeBufferPermanently(): invalid BufferIds:" << bufferId1 << bufferId2 << "for User:" << _coreSession->user(); + return; + } + + if(bufferInfo1.type() != BufferInfo::QueryBuffer || bufferInfo2.type() != BufferInfo::QueryBuffer) { + qWarning() << "CoreBufferSyncer::mergeBufferPermanently(): only QueryBuffers can be merged!" << bufferId1 << bufferId2; + return; + } + + if(Core::mergeBuffersPermanently(_coreSession->user(), bufferId1, bufferId2)) { + qDebug () << "HUUUUP"; + BufferSyncer::mergeBuffersPermanently(bufferId1, bufferId2); + } +} diff --git a/src/core/corebuffersyncer.h b/src/core/corebuffersyncer.h new file mode 100644 index 00000000..0c3a8c04 --- /dev/null +++ b/src/core/corebuffersyncer.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2005-08 by the Quassel Project * + * devel@quassel-irc.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) version 3. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef COREBUFFERSYNCER_H +#define COREBUFFERSYNCER_H + +#include "buffersyncer.h" + +class CoreSession; + +class CoreBufferSyncer : public BufferSyncer { + Q_OBJECT + +public: + CoreBufferSyncer(CoreSession *parent); + +public slots: + virtual void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId); + + virtual inline void requestRemoveBuffer(BufferId buffer) { removeBuffer(buffer); } + virtual void removeBuffer(BufferId bufferId); + + virtual inline void requestRenameBuffer(BufferId buffer, QString newName) { renameBuffer(buffer, newName); } + virtual void renameBuffer(BufferId buffer, QString newName); + + virtual inline void requestMergeBuffersPermanently(BufferId buffer1, BufferId buffer2) { mergeBuffersPermanently(buffer1, buffer2); } + virtual void mergeBuffersPermanently(BufferId buffer1, BufferId buffer2); + + void storeDirtyIds(); + +private: + CoreSession *_coreSession; + + QSet dirtyBuffers; +}; + +#endif //COREBUFFERSYNCER_H diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 841ae7c1..fd9a872e 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -80,7 +80,8 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) foreach(BufferId id, lastSeenHash.keys()) _bufferSyncer->requestSetLastSeenMsg(id, lastSeenHash[id]); - connect(_bufferSyncer, SIGNAL(lastSeenMsgSet(BufferId, MsgId)), this, SLOT(storeBufferLastSeenMsg(BufferId, MsgId))); + // connect(_bufferSyncer, SIGNAL(lastSeenMsgSet(BufferId, MsgId)), this, SLOT(storeBufferLastSeenMsg(BufferId, MsgId))); + connect(&(Core::instance()->syncTimer()), SIGNAL(timeout()), _bufferSyncer, SLOT(storeDirtyIds())); p->synchronize(_bufferSyncer); @@ -158,6 +159,7 @@ void CoreSession::loadSettings() { } void CoreSession::saveSessionState() const { + _bufferSyncer->storeDirtyIds(); } void CoreSession::restoreSessionState() { diff --git a/src/core/sql.qrc b/src/core/sql.qrc index 2c2c50e7..319a5682 100644 --- a/src/core/sql.qrc +++ b/src/core/sql.qrc @@ -77,6 +77,7 @@ ./SQL/SQLite/13/setup_130_identity.sql ./SQL/SQLite/13/setup_140_identity_nick.sql ./SQL/SQLite/13/setup_999_version.sql + ./SQL/SQLite/13/update_backlog_bufferid.sql ./SQL/SQLite/13/update_buffer_lastseen.sql ./SQL/SQLite/13/update_buffer_name.sql ./SQL/SQLite/13/update_buffer_persistent_channel.sql diff --git a/src/core/sqlitestorage.cpp b/src/core/sqlitestorage.cpp index dea348fb..718dc59d 100644 --- a/src/core/sqlitestorage.cpp +++ b/src/core/sqlitestorage.cpp @@ -808,6 +808,27 @@ bool SqliteStorage::renameBuffer(const UserId &user, const BufferId &bufferId, c return true; } +bool SqliteStorage::mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) { + if(!isValidBuffer(user, bufferId1) || !isValidBuffer(user, bufferId2)) + return false; + + QSqlQuery query(logDb()); + query.prepare(queryString("update_backlog_bufferid")); + query.bindValue(":oldbufferid", bufferId2.toInt()); + query.bindValue(":newbufferid", bufferId1.toInt()); + safeExec(query); + if(!watchQuery(query)) + return false; + + QSqlQuery delBufferQuery(logDb()); + delBufferQuery.prepare(queryString("delete_buffer_for_bufferid")); + delBufferQuery.bindValue(":bufferid", bufferId2.toInt()); + safeExec(delBufferQuery); + watchQuery(delBufferQuery); + + return true; +} + void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId) { QSqlQuery query(logDb()); query.prepare(queryString("update_buffer_lastseen")); diff --git a/src/core/sqlitestorage.h b/src/core/sqlitestorage.h index 9b6d2c7c..6ad80fef 100644 --- a/src/core/sqlitestorage.h +++ b/src/core/sqlitestorage.h @@ -80,6 +80,7 @@ public slots: virtual QList requestBufferIdsForNetwork(UserId user, NetworkId networkId); virtual bool removeBuffer(const UserId &user, const BufferId &bufferId); virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName); + virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2); virtual void setBufferLastSeenMsg(UserId user, const BufferId &bufferId, const MsgId &msgId); virtual QHash bufferLastSeenMsgIds(UserId user); diff --git a/src/core/storage.h b/src/core/storage.h index a7aaae91..9612a594 100644 --- a/src/core/storage.h +++ b/src/core/storage.h @@ -274,7 +274,16 @@ public slots: * \return true if successfull */ virtual bool renameBuffer(const UserId &user, const BufferId &bufferId, const QString &newName) = 0; - + + //! Merge the content of two Buffers permanently. This cannot be reversed! + /** \note This method is threadsafe. + * \param user The id of the buffer owner + * \param bufferId1 The bufferId of the remaining buffer + * \param bufferId2 The buffer that is about to be removed + * \return true if successfull + */ + virtual bool mergeBuffersPermanently(const UserId &user, const BufferId &bufferId1, const BufferId &bufferId2) = 0; + //! Update the LastSeenDate for a Buffer /** This Method is used to make the LastSeenDate of a Buffer persistent * \param user The Owner of that Buffer diff --git a/src/uisupport/bufferview.cpp b/src/uisupport/bufferview.cpp index eadf8f77..c8834341 100644 --- a/src/uisupport/bufferview.cpp +++ b/src/uisupport/bufferview.cpp @@ -196,6 +196,37 @@ void BufferView::keyPressEvent(QKeyEvent *event) { QTreeView::keyPressEvent(event); } +void BufferView::dropEvent(QDropEvent *event) { + QList< QPair > bufferList = Client::networkModel()->mimeDataToBufferList(event->mimeData()); + + if(bufferList.count() != 1) + return QTreeView::dropEvent(event); + + NetworkId networkId = bufferList[0].first; + BufferId bufferId2 = bufferList[0].second; + + QModelIndex index = indexAt(event->pos()); + if(index.data(NetworkModel::ItemTypeRole) != NetworkModel::BufferItemType) + return; + + if(index.data(NetworkModel::BufferTypeRole) != BufferInfo::QueryBuffer) + return; + + if(index.data(NetworkModel::NetworkIdRole).value() != networkId) + return; + + BufferId bufferId1 = index.data(NetworkModel::BufferIdRole).value(); + if(bufferId1 == bufferId2) + return; + + int res = QMessageBox::question(0, tr("Merge buffers permanently?"), + tr("Do you want to merge the buffer \"%1\" permanently into buffer \"%2\"?\n This cannot be reversed!").arg(Client::networkModel()->bufferName(bufferId2)).arg(Client::networkModel()->bufferName(bufferId1)), + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if(res == QMessageBox::Yes) { + Client::mergeBuffersPermanently(bufferId1, bufferId2); + } +} + void BufferView::removeSelectedBuffers(bool permanently) { if(!config()) return; diff --git a/src/uisupport/bufferview.h b/src/uisupport/bufferview.h index ad411a89..032cd0fe 100644 --- a/src/uisupport/bufferview.h +++ b/src/uisupport/bufferview.h @@ -63,6 +63,7 @@ signals: protected: virtual void keyPressEvent(QKeyEvent *); + virtual void dropEvent(QDropEvent *event); virtual void rowsInserted(const QModelIndex & parent, int start, int end); virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); virtual void wheelEvent(QWheelEvent *); -- 2.20.1