socket->deleteLater();
}
_syncedToCore = false;
- setCurrentCoreAccount(0);
emit disconnected();
emit coreConnectionStateChanged(false);
// Clear internal data. Hopefully nothing relies on it at this point.
+ setCurrentCoreAccount(0);
+
if(_bufferSyncer) {
_bufferSyncer->deleteLater();
_bufferSyncer = 0;
QList<AccountId> CoreAccountSettings::knownAccounts() {
QList<AccountId> ids;
foreach(QString key, localChildGroups()) {
- ids << key.toInt();
+ AccountId acc = key.toInt();
+ if(acc.isValid()) ids << acc;
}
return ids;
}
}
void BufferViewConfig::addBuffer(const BufferId &bufferId, int pos) {
- qDebug() << "addBuffer" << bufferId;
if(_buffers.contains(bufferId))
return;
+
+ if(pos < 0)
+ pos = 0;
+ if(pos > _buffers.count())
+ pos = _buffers.count();
_buffers.insert(pos, bufferId);
emit bufferAdded(bufferId, pos);
}
void BufferViewConfig::moveBuffer(const BufferId &bufferId, int pos) {
- qDebug() << "moveeBuffer" << bufferId;
if(!_buffers.contains(bufferId))
return;
- qDebug() << "lala" << bufferId << pos;
+ if(pos < 0)
+ pos = 0;
+ if(pos >= _buffers.count())
+ pos = _buffers.count() - 1;
+
_buffers.move(_buffers.indexOf(bufferId), pos);
emit bufferMoved(bufferId, pos);
}
void BufferViewConfig::removeBuffer(const BufferId &bufferId) {
- qDebug() << "removeBuffer" << bufferId;
if(!_buffers.contains(bufferId))
return;
// called now only on /quit and requested disconnects, not on normal disconnects!
void CoreSession::networkDisconnected(NetworkId networkid) {
- Core::setNetworkConnected(user(), networkid, false);
- if(_connections.contains(networkid)) _connections.take(networkid)->deleteLater();
+ // if the network has already been removed, we don't have a networkconnection left either, so we don't do anything
+ // make sure to not depend on the network still existing when calling this function!
+ if(_connections.contains(networkid)) {
+ Core::setNetworkConnected(user(), networkid, false);
+ _connections.take(networkid)->deleteLater();
+ }
}
void CoreSession::channelJoined(NetworkId id, const QString &channel, const QString &key) {
}
void CoreSession::destroyNetwork(NetworkId id) {
- Q_ASSERT(!_connections.contains(id));
+ if(_connections.contains(id)) {
+ // this can happen if the network was reconnecting while being removed
+ _connections.take(id)->deleteLater();
+ }
Network *net = _networks.take(id);
if(net && Core::removeNetwork(user(), id)) {
emit networkRemoved(id);
#include "networkconnection.h"
#include "network.h"
#include "ctcphandler.h"
+#include "ircuser.h"
#include <QDebug>
}
void UserInputHandler::handleBan(const BufferInfo &bufferInfo, const QString &msg) {
- if(bufferInfo.type() != BufferInfo::ChannelBuffer)
+ QString banChannel;
+ QString banUser;
+
+ QStringList params = msg.split(" ");
+
+ if(!params.isEmpty() && isChannelName(params[0])) {
+ banChannel = params.takeFirst();
+ } else if(bufferInfo.type() == BufferInfo::ChannelBuffer) {
+ banChannel = bufferInfo.bufferName();
+ } else {
+ emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", QString("Error: channel unknown in command: /BAN %1").arg(msg));
return;
-
- //TODO: find suitable default hostmask if msg gives only nickname
- // Example: MODE &oulu +b *!*@*
- QByteArray banMsg = serverEncode(bufferInfo.bufferName()) + " +b " + channelEncode(bufferInfo.bufferName(), msg);
- emit putCmd("MODE", banMsg);
+ }
+
+ if(!params.isEmpty() && !params.contains("!") && network()->ircUser(params[0])) {
+ IrcUser *ircuser = network()->ircUser(params[0]);
+ // generalizedHost changes <nick> to *!ident@*.sld.tld.
+ QString generalizedHost = ircuser->host();
+ if(generalizedHost.isEmpty()) {
+ emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", QString("Error: host unknown in command: /BAN %1").arg(msg));
+ return;
+ }
+
+ if(generalizedHost.lastIndexOf(".") != -1 && generalizedHost.lastIndexOf(".", generalizedHost.lastIndexOf(".")-1) != -1) {
+ int secondLastPeriodPosition = generalizedHost.lastIndexOf(".", generalizedHost.lastIndexOf(".")-1);
+ generalizedHost.replace(0, secondLastPeriodPosition, "*");
+ }
+ banUser = QString("*!%1@%2").arg(ircuser->user()).arg(generalizedHost);
+ } else {
+ banUser = params.join(" ");
+ }
+
+ QString banMsg = QString("MODE %1 +b %2").arg(banChannel).arg(banUser);
+ qDebug() << banMsg;
+ emit putRawLine(serverEncode(banMsg));
}
void UserInputHandler::handleCtcp(const BufferInfo &bufferInfo, const QString &msg) {
emit putCmd("KICK", params);
}
+void UserInputHandler::handleKill(const BufferInfo &bufferInfo, const QString &msg) {
+ QString nick = msg.section(' ', 0, 0, QString::SectionSkipEmpty);
+ QString pass = msg.section(' ', 1, -1, QString::SectionSkipEmpty);
+ QList<QByteArray> params;
+ params << serverEncode(nick) << serverEncode(pass);
+ emit putCmd("KILL", params);
+}
+
+
void UserInputHandler::handleList(const BufferInfo &bufferInfo, const QString &msg) {
Q_UNUSED(bufferInfo)
emit putCmd("LIST", serverEncode(msg.split(' ', QString::SkipEmptyParts)));
emit putCmd("MODE", serverEncode(params));
}
+void UserInputHandler::handleOper(const BufferInfo &bufferInfo, const QString &msg) {
+ emit putRawLine(serverEncode(QString("OPER %1").arg(msg)));
+}
+
void UserInputHandler::handlePart(const BufferInfo &bufferInfo, const QString &msg) {
QList<QByteArray> params;
params << serverEncode(bufferInfo.bufferName()) << channelEncode(bufferInfo.bufferName(), msg);
void handleJ(const BufferInfo &bufferInfo, const QString &text);
void handleJoin(const BufferInfo &bufferInfo, const QString &text);
void handleKick(const BufferInfo &bufferInfo, const QString &text);
+ void handleKill(const BufferInfo &bufferInfo, const QString &text);
void handleList(const BufferInfo &bufferInfo, const QString &text);
void handleMe(const BufferInfo &bufferInfo, const QString &text);
void handleMode(const BufferInfo &bufferInfo, const QString &text);
void handleMsg(const BufferInfo &bufferInfo, const QString &text);
void handleNick(const BufferInfo &bufferInfo, const QString &text);
+ void handleOper(const BufferInfo &bufferInfo, const QString &text);
void handleOp(const BufferInfo &bufferInfo, const QString &text);
void handlePart(const BufferInfo &bufferInfo, const QString &text);
void handleQuery(const BufferInfo &bufferInfo, const QString &text);
foreach(AccountId id, s.knownAccounts()) {
if(!id.isValid()) continue;
QVariantMap data = s.retrieveAccountData(id);
+ data["AccountId"] = QVariant::fromValue<AccountId>(id);
accounts[id] = data;
QListWidgetItem *item = new QListWidgetItem(data["AccountName"].toString(), ui.accountList);
item->setData(Qt::UserRole, QVariant::fromValue<AccountId>(id));
Client::signalProxy()->attachSignal(this, SIGNAL(requestBacklog(BufferInfo, QVariant, QVariant)));
+ connect(QApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(saveLayout()));
+
connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientNetworkCreated(NetworkId)));
connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientNetworkRemoved(NetworkId)));
//ui.bufferWidget->init();
// restore mainwin state
restoreState(s.value("MainWinState").toByteArray());
- disconnectedFromCore(); // Disable menus and stuff
+ setDisconnectedState(); // Disable menus and stuff
showCoreConnectionDlg(true); // autoconnect if appropriate
// attach the BufferWidget to the BufferModel and the default selection
break;
dock = qobject_cast<BufferViewDock *>(action->parent());
- if(dock && actionData.toInt() != bufferViewConfigId) {
+ if(dock && actionData.toInt() == bufferViewConfigId) {
removeAction(action);
dock->deleteLater();
}
foreach(BufferInfo id, Client::allBufferInfos()) {
Client::backlogManager()->requestBacklog(id.bufferId(), 500, -1);
}
+ setConnectedState();
+}
+void MainWin::setConnectedState() {
ui.menuViews->setEnabled(true);
//ui.menuCore->setEnabled(true);
ui.actionConnectCore->setEnabled(false);
restoreState(s.value(QString("MainWinState-%1").arg(accountId)).toByteArray(), accountId);
}
+void MainWin::saveLayout() {
+ QtUiSettings s;
+ int accountId = Client::currentCoreAccount().toInt();
+ if(accountId > 0) s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId));
+}
+
void MainWin::securedConnection() {
// todo: make status bar entry
qDebug() << "secured the connection";
void MainWin::disconnectedFromCore() {
// save core specific layout and remove bufferviews;
- QtUiSettings s;
- int accountId = Client::currentCoreAccount().toInt();
- s.setValue(QString("MainWinState-%1").arg(accountId) , saveState(accountId));
+ saveLayout();
QVariant actionData;
BufferViewDock *dock;
foreach(QAction *action, ui.menuViews->actions()) {
dock->deleteLater();
}
}
+ QtUiSettings s;
+ restoreState(s.value("MainWinState").toByteArray());
+ setDisconnectedState();
+}
+void MainWin::setDisconnectedState() {
ui.menuViews->setEnabled(false);
//ui.menuCore->setEnabled(false);
ui.actionDisconnectCore->setEnabled(false);
protected slots:
void connectedToCore();
+ void setConnectedState();
void securedConnection();
void disconnectedFromCore();
+ void setDisconnectedState();
void systrayActivated( QSystemTrayIcon::ActivationReason );
private slots:
void saveStatusBarStatus(bool enabled);
void loadLayout();
+ void saveLayout();
signals:
void connectToCore(const QVariantMap &connInfo);
BufferViewConfig *changedConfig = new BufferViewConfig(-1, this);
changedConfig->fromVariantMap(config->toVariantMap());
_changedBufferViews[config] = changedConfig;
+ connect(config, SIGNAL(bufferAdded(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
+ connect(config, SIGNAL(bufferMoved(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
+ connect(config, SIGNAL(bufferRemoved(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
+ connect(config, SIGNAL(addBufferRequested(const BufferId &, int)), changedConfig, SLOT(addBuffer(const BufferId &, int)));
+ connect(config, SIGNAL(moveBufferRequested(const BufferId &, int)), changedConfig, SLOT(moveBuffer(const BufferId &, int)));
+ connect(config, SIGNAL(removeBufferRequested(const BufferId &)), changedConfig, SLOT(removeBuffer(const BufferId &)));
// if this is the currently displayed view we have to change the config of the preview filter
BufferViewFilter *filter = qobject_cast<BufferViewFilter *>(ui.bufferViewPreview->model());
<ui version="4.0" >
<class>NetworksSettingsPage</class>
<widget class="QWidget" name="NetworksSettingsPage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>736</width>
+ <height>452</height>
+ </rect>
+ </property>
<property name="windowTitle" >
<string>Form</string>
</property>
<string>Re&name...</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/edit-rename.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/edit-rename.png</normaloff>:/16x16/actions/oxygen/16x16/actions/edit-rename.png</iconset>
</property>
</widget>
</item>
<string>&Add...</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/list-add.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/list-add.png</normaloff>:/16x16/actions/oxygen/16x16/actions/list-add.png</iconset>
</property>
<property name="iconSize" >
<size>
<string>De&lete</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/edit-delete.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</iconset>
</property>
</widget>
</item>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" >
+ <property name="sizeHint" stdset="0" >
<size>
<width>131</width>
<height>71</height>
<string>Connect now</string>
</property>
<property name="icon" >
- <iconset/>
+ <iconset>
+ <normaloff/>
+ </iconset>
</property>
</widget>
</item>
Unless you *really* know what you do, leave this as ISO-8859-1!</string>
</property>
<property name="currentIndex" >
- <number>0</number>
+ <number>1</number>
</property>
<widget class="QWidget" name="serversTab" >
<property name="enabled" >
<bool>true</bool>
</property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>398</width>
+ <height>326</height>
+ </rect>
+ </property>
<attribute name="title" >
<string>Servers</string>
</attribute>
<string>&Edit...</string>
</property>
<property name="icon" >
- <iconset/>
+ <iconset>
+ <normaloff/>
+ </iconset>
</property>
</widget>
</item>
<string>&Add...</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/list-add.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/list-add.png</normaloff>:/16x16/actions/oxygen/16x16/actions/list-add.png</iconset>
</property>
</widget>
</item>
<string>De&lete</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/edit-delete.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</iconset>
</property>
</widget>
</item>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" >
+ <property name="sizeHint" stdset="0" >
<size>
<width>0</width>
<height>20</height>
<string>...</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/go-up.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/go-up.png</normaloff>:/16x16/actions/oxygen/16x16/actions/go-up.png</iconset>
</property>
</widget>
</item>
<string>...</string>
</property>
<property name="icon" >
- <iconset resource="../../icons/icons.qrc" >:/16x16/actions/oxygen/16x16/actions/go-down.png</iconset>
+ <iconset resource="../../icons/icons.qrc" >
+ <normaloff>:/16x16/actions/oxygen/16x16/actions/go-down.png</normaloff>:/16x16/actions/oxygen/16x16/actions/go-down.png</iconset>
</property>
</widget>
</item>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
- <property name="sizeHint" >
+ <property name="sizeHint" stdset="0" >
<size>
<width>0</width>
<height>20</height>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
- <property name="sizeHint" >
+ <property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>40</height>
</layout>
</widget>
<widget class="QWidget" name="performTab" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>398</width>
+ <height>326</height>
+ </rect>
+ </property>
<attribute name="title" >
<string>Perform</string>
</attribute>
- <layout class="QVBoxLayout" >
+ <layout class="QVBoxLayout" name="verticalLayout" >
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<property name="checked" >
<bool>true</bool>
</property>
- <widget class="QWidget" name="" >
- <layout class="QGridLayout" >
- <item row="0" column="0" >
- <widget class="QLabel" name="label_2" >
- <property name="text" >
- <string>Service:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1" >
- <widget class="QLineEdit" name="autoIdentifyService" >
- <property name="enabled" >
- <bool>true</bool>
- </property>
- <property name="text" >
- <string>NickServ</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" >
- <widget class="QLabel" name="label_3" >
- <property name="enabled" >
- <bool>true</bool>
- </property>
- <property name="text" >
- <string>Password:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1" >
- <widget class="QLineEdit" name="autoIdentifyPassword" >
- <property name="enabled" >
- <bool>true</bool>
- </property>
- <property name="echoMode" >
- <enum>QLineEdit::Password</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
</widget>
</item>
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Service:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="autoIdentifyService" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>NickServ</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="text" >
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLineEdit" name="autoIdentifyPassword" >
+ <property name="enabled" >
+ <bool>true</bool>
+ </property>
+ <property name="echoMode" >
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
<widget class="QWidget" name="tab" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>398</width>
+ <height>326</height>
+ </rect>
+ </property>
<attribute name="title" >
<string>Advanced</string>
</attribute>
#include <QColor>
+#include "buffermodel.h"
#include "client.h"
#include "networkmodel.h"
{
setConfig(config);
setSourceModel(model);
+ connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(source_rowsInserted(const QModelIndex &, int, int)));
+
// setSortCaseSensitivity(Qt::CaseInsensitive);
setDynamicSortFilter(true);
}
networkId = bufferList[i].first;
bufferId = bufferList[i].second;
if(droppedNetworkId == networkId) {
+ if(row < 0)
+ row = 0;
if(row < rowCount(parent)) {
BufferId beforeBufferId = parent.child(row, 0).data(NetworkModel::BufferIdRole).value<BufferId>();
pos = config()->bufferList().indexOf(beforeBufferId);
bool BufferViewFilter::filterAcceptBuffer(const QModelIndex &source_bufferIndex) const {
if(!_config)
return true;
-
+
if(!(_config->allowedBufferTypes() & (BufferInfo::Type)source_bufferIndex.data(NetworkModel::BufferTypeRole).toInt()))
return false;
if(_config->hideInactiveBuffers() && !source_bufferIndex.data(NetworkModel::ItemActiveRole).toBool())
return false;
- if(_config->minimumActivity() > source_bufferIndex.data(NetworkModel::BufferActivityRole).toInt())
- return false;
+ if(_config->minimumActivity() > source_bufferIndex.data(NetworkModel::BufferActivityRole).toInt()) {
+ if(!Client::bufferModel()->standardSelectionModel()->isSelected(source_bufferIndex))
+ return false;
+ }
- BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value<BufferId>();
- return _config->bufferList().contains(bufferId);
+ BufferId bufferId = sourceModel()->data(source_bufferIndex, NetworkModel::BufferIdRole).value<BufferId>();
+ return _config->bufferList().contains(bufferId);
}
bool BufferViewFilter::filterAcceptNetwork(const QModelIndex &source_index) const {
}
+void BufferViewFilter::source_rowsInserted(const QModelIndex &parent, int start, int end) {
+ if(parent.data(NetworkModel::ItemTypeRole) != NetworkModel::NetworkItemType)
+ return;
+
+ if(!config() || !config()->addNewBuffersAutomatically())
+ return;
+
+ for(int row = start; row <= end; row++) {
+ addBuffer(parent.child(row, 0).data(NetworkModel::BufferIdRole).value<BufferId>());
+ }
+}
// ******************************
// Helper
public slots:
void removeBuffer(const QModelIndex &);
+ void source_rowsInserted(const QModelIndex &parent, int start, int end);
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
QAction *deVoiceAction = modeMenu->addAction(tr("Devoice %1").arg(nick));
QMenu *kickBanMenu = nickContextMenu.addMenu(tr("Kick/Ban"));
- //TODO: add kick message from network identity (kick reason)
QAction *kickAction = kickBanMenu->addAction(tr("Kick %1").arg(nick));
+ QAction *banAction = kickBanMenu->addAction(tr("Ban %1").arg(nick));
QAction *kickBanAction = kickBanMenu->addAction(tr("Kickban %1").arg(nick));
- kickBanMenu->setEnabled(false);
QAction *ignoreAction = nickContextMenu.addAction(tr("Ignore"));
ignoreAction->setEnabled(false);
else if(action == deVoiceAction) { executeCommand(bufferInfo, QString("/DEVOICE %1").arg(nick)); }
else if(action == kickAction) { executeCommand(bufferInfo, QString("/KICK %1").arg(nick)); }
- else if(action == kickBanAction) { executeCommand(bufferInfo, QString("/KICKBAN %1").arg(nick)); }
+ else if(action == banAction) { executeCommand(bufferInfo, QString("/BAN %1").arg(nick)); }
+ else if(action == kickBanAction) { executeCommand(bufferInfo, QString("/KICK %1").arg(nick));
+ executeCommand(bufferInfo, QString("/BAN %1").arg(nick)); }
else if(action == queryAction) { executeCommand(bufferInfo, QString("/QUERY %1").arg(nick)); }
}
{ using namespace Global;
quasselVersion = "0.2.0-beta1-pre";
- quasselDate = "2008-04-13";
- quasselBuild = 733;
+ quasselDate = "2008-04-14";
+ quasselBuild = 745;
//! Minimum client build number the core needs
clientBuildNeeded = 731;