You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
konversation/konversation/src/query.cpp

674 lines
21 KiB

/*
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) any later version.
*/
/*
Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
Copyright (C) 2005-2008 Eike Hein <hein@kde.org>
*/
#include "query.h"
#include "channel.h"
#include "server.h"
#include "konversationapplication.h"
#include "konversationmainwindow.h"
#include "viewcontainer.h"
#include "ircinput.h"
#include "ircview.h"
#include "ircviewbox.h"
#include "common.h"
#include "topiclabel.h"
#include <tqhbox.h>
#include <tqcheckbox.h>
#include <tqlabel.h>
#include <tqlineedit.h>
#include <tqtextcodec.h>
#include <tqtooltip.h>
#include <tqtextstream.h>
#include <tqwhatsthis.h>
#include <tqsplitter.h>
#include <tdelocale.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <tdemessagebox.h>
#include <kiconloader.h>
#include <kstringhandler.h>
#include <tdepopupmenu.h>
Query::Query(TQWidget* parent, TQString _name) : ChatWindow(parent)
{
name=_name; // need the name a little bit earlier for setServer
// don't setName here! It will break logfiles!
// setName("QueryWidget");
setType(ChatWindow::Query);
setChannelEncodingSupported(true);
m_headerSplitter = new TQSplitter(Qt::Vertical, this);
m_initialShow = true;
awayChanged=false;
awayState=false;
TQHBox *box = new TQHBox(m_headerSplitter);
addresseeimage = new TQLabel(box, "query_image");
addresseeimage->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed);
addresseeimage->hide();
addresseelogoimage = new TQLabel(box, "query_logo_image");
addresseelogoimage->setSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed);
addresseelogoimage->hide();
queryHostmask=new Konversation::TopicLabel(box, "query_hostmask");
TQString whatsthis = i18n("<qt>Some details of the person you are talking to in this query is shown in this bar. The full name and hostmask is shown, along with any image or logo this person has associated with them in the TDE Addressbook.<p>See the <i>Konversation Handbook</i> for information on associating a nick with a contact in the Addressbook, and for an explanation of what the hostmask is.</qt>");
TQWhatsThis::add(addresseeimage, whatsthis);
TQWhatsThis::add(addresseelogoimage, whatsthis);
TQWhatsThis::add(queryHostmask, whatsthis);
IRCViewBox* ircBox = new IRCViewBox(m_headerSplitter,0);
setTextView(ircBox->ircView()); // Server will be set later in setServer();
textView->setAcceptDrops(true);
connect(textView,TQT_SIGNAL(filesDropped(const TQStrList&)),this,TQT_SLOT(filesDropped(const TQStrList&)));
connect(textView,TQT_SIGNAL(popupCommand(int)),this,TQT_SLOT(popup(int)));
// link "Whois", "Ignore" ... menu items into ircview popup
TQPopupMenu* popup=textView->getPopup();
popup->insertSeparator();
popup->insertItem(i18n("&Whois"),Konversation::Whois);
popup->insertItem(i18n("&Version"),Konversation::Version);
popup->insertItem(i18n("&Ping"),Konversation::Ping);
popup->insertSeparator();
popup->insertItem(i18n("Ignore"), Konversation::IgnoreNick);
popup->insertItem(i18n("Unignore"), Konversation::UnignoreNick);
popup->setItemVisible(Konversation::IgnoreNick, false);
popup->setItemVisible(Konversation::UnignoreNick, false);
if (kapp->authorize("allow_downloading"))
popup->insertItem(SmallIcon("2rightarrow"),i18n("Send &File..."),Konversation::DccSend);
popup->insertItem(i18n("Add to Watched Nicks"), Konversation::AddNotify);
// This box holds the input line
TQHBox* inputBox=new TQHBox(this, "input_log_box");
inputBox->setSpacing(spacing());
awayLabel=new TQLabel(i18n("(away)"),inputBox);
awayLabel->hide();
blowfishLabel = new TQLabel(inputBox);
blowfishLabel->hide();
blowfishLabel->setPixmap(TDEGlobal::iconLoader()->loadIcon("encrypted", TDEIcon::Toolbar));
queryInput=new IRCInput(inputBox);
getTextView()->installEventFilter(queryInput);
queryInput->installEventFilter(this);
// connect the signals and slots
connect(queryInput,TQT_SIGNAL (submit()),this,TQT_SLOT (queryTextEntered()) );
connect(queryInput,TQT_SIGNAL (envelopeCommand()),this,TQT_SLOT (queryPassthroughCommand()) );
connect(queryInput,TQT_SIGNAL (textPasted(const TQString&)),this,TQT_SLOT (textPasted(const TQString&)) );
connect(getTextView(), TQT_SIGNAL(textPasted(bool)), queryInput, TQT_SLOT(paste(bool)));
connect(getTextView(),TQT_SIGNAL (gotFocus()),queryInput,TQT_SLOT (setFocus()) );
connect(textView,TQT_SIGNAL (sendFile()),this,TQT_SLOT (sendFileMenu()) );
connect(textView,TQT_SIGNAL (extendedPopup(int)),this,TQT_SLOT (popup(int)) );
connect(textView,TQT_SIGNAL (autoText(const TQString&)),this,TQT_SLOT (sendQueryText(const TQString&)) );
updateAppearance();
setLog(Preferences::log());
}
Query::~Query()
{
}
void Query::setServer(Server* newServer)
{
if (m_server != newServer)
connect(newServer, TQT_SIGNAL(connectionStateChanged(Server*, Konversation::ConnectionState)),
TQT_SLOT(connectionStateChanged(Server*, Konversation::ConnectionState)));
ChatWindow::setServer(newServer);
if (!newServer->getKeyForRecipient(getName()).isNull())
blowfishLabel->show();
}
void Query::connectionStateChanged(Server* server, Konversation::ConnectionState state)
{
if (server == m_server)
{
if (state == Konversation::SSConnected)
{
//HACK the way the notification priorities work sucks, this forces the tab text color to ungray right now.
if (m_currentTabNotify == Konversation::tnfNone || !Preferences::tabNotificationsEvents())
KonversationApplication::instance()->getMainWindow()->getViewContainer()->unsetViewNotification(this);
}
else
{
//HACK the way the notification priorities work sucks, this forces the tab text color to gray right now.
if (m_currentTabNotify == Konversation::tnfNone || (!Preferences::tabNotificationsEvents() && m_currentTabNotify == Konversation::tnfControl))
KonversationApplication::instance()->getMainWindow()->getViewContainer()->unsetViewNotification(this);
}
}
}
void Query::setName(const TQString& newName)
{
//if(ChatWindow::getName() == newName) return; // no change, so return
ChatWindow::setName(newName);
// don't change logfile name if query name changes
// This will prevent Nick-Changers to create more than one log file,
if (logName.isEmpty())
{
TQString logName = (Preferences::lowerLog()) ? getName().lower() : getName() ;
if(Preferences::addHostnameToLog())
{
if(m_nickInfo)
logName += m_nickInfo->getHostmask();
}
setLogfileName(logName);
}
}
void Query::setEncryptedOutput(bool e)
{
if (e)
blowfishLabel->show();
else
blowfishLabel->hide();
}
void Query::queryTextEntered()
{
TQString line=queryInput->text();
queryInput->setText("");
if(line.lower()==Preferences::commandChar()+"clear")
{
textView->clear();
}
else if(line.lower()==Preferences::commandChar()+"part")
{
m_server->closeQuery(getName());
}
else if(line.length())
{
sendQueryText(line);
}
}
void Query::queryPassthroughCommand()
{
TQString commandChar = Preferences::commandChar();
TQString line = queryInput->text();
queryInput->setText("");
if(!line.isEmpty())
{
// Prepend commandChar on Ctrl+Enter to bypass outputfilter command recognition
if (line.startsWith(commandChar))
{
line = commandChar + line;
}
sendQueryText(line);
}
}
void Query::sendQueryText(const TQString& sendLine)
{
// create a work copy
TQString outputAll(sendLine);
// replace aliases and wildcards
if(m_server->getOutputFilter()->replaceAliases(outputAll))
{
outputAll = m_server->parseWildcards(outputAll, m_server->getNickname(), getName(), TQString(), TQString(), TQString());
}
// Send all strings, one after another
TQStringList outList=TQStringList::split('\n',outputAll);
for(unsigned int index=0;index<outList.count();index++)
{
TQString output(outList[index]);
// encoding stuff is done in Server()
Konversation::OutputFilterResult result = m_server->getOutputFilter()->parse(m_server->getNickname(), output, getName());
if(!result.output.isEmpty())
{
if(result.type == Konversation::Action) appendAction(m_server->getNickname(), result.output);
else if(result.type == Konversation::Command) appendCommandMessage(result.typeString, result.output);
else if(result.type == Konversation::Program) appendServerMessage(result.typeString, result.output);
else if(!result.typeString.isEmpty()) appendQuery(result.typeString, result.output);
else appendQuery(m_server->getNickname(), result.output);
}
else if (result.outputList.count())
{
Q_ASSERT(result.type==Konversation::Message);
for ( TQStringList::Iterator it = result.outputList.begin(); it != result.outputList.end(); ++it )
{
append(m_server->getNickname(), *it);
}
}
if (!result.toServerList.empty())
{
m_server->queueList(result.toServerList);
}
else
{
m_server->queue(result.toServer);
}
} // for
}
void Query::updateAppearance()
{
TQColor fg;
TQColor bg;
if(Preferences::inputFieldsBackgroundColor())
{
fg=Preferences::color(Preferences::ChannelMessage);
bg=Preferences::color(Preferences::TextViewBackground);
}
else
{
fg=colorGroup().foreground();
bg=colorGroup().base();
}
queryInput->unsetPalette();
queryInput->setPaletteForegroundColor(fg);
queryInput->setPaletteBackgroundColor(bg);
getTextView()->unsetPalette();
if (Preferences::showBackgroundImage())
{
getTextView()->setViewBackground(Preferences::color(Preferences::TextViewBackground),
Preferences::backgroundImage());
}
else
{
getTextView()->setViewBackground(Preferences::color(Preferences::TextViewBackground),
TQString());
}
if (Preferences::customTextFont())
{
getTextView()->setFont(Preferences::textFont());
queryInput->setFont(Preferences::textFont());
}
else
{
getTextView()->setFont(TDEGlobalSettings::generalFont());
queryInput->setFont(TDEGlobalSettings::generalFont());
}
ChatWindow::updateAppearance();
}
void Query::textPasted(const TQString& text)
{
if(m_server)
{
TQStringList multiline=TQStringList::split('\n',text);
for(unsigned int index=0;index<multiline.count();index++)
{
TQString line=multiline[index];
TQString cChar(Preferences::commandChar());
// make sure that lines starting with command char get escaped
if(line.startsWith(cChar)) line=cChar+line;
sendQueryText(line);
}
}
}
void Query::indicateAway(bool show)
{
// QT does not redraw the label properly when they are not on screen
// while getting hidden, so we remember the "soon to be" state here.
if(isHidden())
{
awayChanged=true;
awayState=show;
}
else
{
if(show)
awayLabel->show();
else
awayLabel->hide();
}
}
// fix TQTs broken behavior on hidden TQListView pages
void Query::showEvent(TQShowEvent*)
{
if(awayChanged)
{
awayChanged=false;
indicateAway(awayState);
}
if(m_initialShow) {
m_initialShow = false;
TQValueList<int> sizes;
sizes << queryHostmask->sizeHint().height() << (height() - queryHostmask->sizeHint().height());
m_headerSplitter->setSizes(sizes);
}
}
void Query::popup(int id)
{
// get the nickname to the context menu popup
TQString name = textView->getContextNick();
// if there was none (right click into the text view) assume query partner
if (name.isEmpty()) name = getName();
switch (id)
{
case Konversation::Whois:
sendQueryText(Preferences::commandChar()+"WHOIS "+name+' '+name);
break;
case Konversation::IgnoreNick:
{
if (KMessageBox::warningContinueCancel(this, i18n("Do you want to ignore %1?").arg(name),
i18n("Ignore"), i18n("Ignore"), "IgnoreNick") == KMessageBox::Continue)
{
sendQueryText(Preferences::commandChar()+"IGNORE -ALL "+name);
int rc = KMessageBox::questionYesNo(this,
i18n("Do you want to close this query after ignoring this nickname?"),
i18n("Close This Query"),
i18n("Close"),
i18n("Keep Open"),
"CloseQueryAfterIgnore");
if (rc == KMessageBox::Yes && m_server)
TQTimer::singleShot(0, this, TQT_SLOT(closeWithoutAsking()));
}
break;
}
case Konversation::UnignoreNick:
{
TQString question = i18n("Do you want to stop ignoring %1?").arg(name);
if (KMessageBox::warningContinueCancel(this, question, i18n("Unignore"), i18n("Unignore"), "UnignoreNick") ==
KMessageBox::Continue)
{
sendQueryText(Preferences::commandChar()+"UNIGNORE "+name);
}
break;
}
case Konversation::AddNotify:
{
if (m_server->getServerGroup())
{
if (!Preferences::isNotify(m_server->getServerGroup()->id(), name))
Preferences::addNotify(m_server->getServerGroup()->id(),name);
}
break;
}
case Konversation::DccSend:
sendQueryText(Preferences::commandChar()+"DCC SEND "+name);
break;
case Konversation::Version:
sendQueryText(Preferences::commandChar()+"CTCP "+name+" VERSION");
break;
case Konversation::Ping:
sendQueryText(Preferences::commandChar()+"CTCP "+name+" PING");
break;
case Konversation::Topic:
m_server->requestTopic(getTextView()->currentChannel());
break;
case Konversation::Names:
m_server->queue("NAMES " + getTextView()->currentChannel(), Server::LowPriority);
break;
case Konversation::Join:
m_server->queue("JOIN " + getTextView()->currentChannel());
break;
default:
kdDebug() << "Query::popup(): Popup id " << id << " does not belong to me!" << endl;
break;
}
// delete context menu nickname
textView->clearContextNick();
}
void Query::sendFileMenu()
{
emit sendFile(getName());
}
void Query::childAdjustFocus()
{
queryInput->setFocus();
}
void Query::setNickInfo(const NickInfoPtr & nickInfo)
{
if(m_nickInfo)
disconnect(m_nickInfo, TQT_SIGNAL(nickInfoChanged()), this, TQT_SLOT(nickInfoChanged()));
m_nickInfo = nickInfo;
Q_ASSERT(m_nickInfo); if(!m_nickInfo) return;
setName(m_nickInfo->getNickname());
connect(m_nickInfo, TQT_SIGNAL(nickInfoChanged()), this, TQT_SLOT(nickInfoChanged()));
nickInfoChanged();
}
void Query::nickInfoChanged()
{
if(m_nickInfo)
{
setName(m_nickInfo->getNickname());
TQString text = m_nickInfo->getBestAddresseeName();
if(!m_nickInfo->getHostmask().isEmpty() && !text.isEmpty())
text += " - ";
text += m_nickInfo->getHostmask();
if(m_nickInfo->isAway() && !m_nickInfo->getAwayMessage().isEmpty())
text += " (" + KStringHandler::rsqueeze(m_nickInfo->getAwayMessage(),100) + ") ";
queryHostmask->setText(Konversation::removeIrcMarkup(text));
KABC::Picture pic = m_nickInfo->getAddressee().photo();
if(pic.isIntern())
{
TQPixmap qpixmap(pic.data().scaleHeight(queryHostmask->height()));
if(!qpixmap.isNull())
{
addresseeimage->setPixmap(qpixmap);
addresseeimage->show();
}
else
{
addresseeimage->hide();
}
}
else
{
addresseeimage->hide();
}
KABC::Picture logo = m_nickInfo->getAddressee().logo();
if(logo.isIntern())
{
TQPixmap qpixmap(logo.data().scaleHeight(queryHostmask->height()));
if(!qpixmap.isNull())
{
addresseelogoimage->setPixmap(qpixmap);
addresseelogoimage->show();
}
else
{
addresseelogoimage->hide();
}
}
else
{
addresseelogoimage->hide();
}
TQString strTooltip;
TQTextStream tooltip( &strTooltip, IO_WriteOnly );
tooltip << "<qt>";
tooltip << "<table cellspacing=\"0\" cellpadding=\"0\">";
m_nickInfo->tooltipTableData(tooltip);
tooltip << "</table></qt>";
TQToolTip::add(queryHostmask, strTooltip);
TQToolTip::add(addresseeimage, strTooltip);
TQToolTip::add(addresseelogoimage, strTooltip);
}
else
{
addresseeimage->hide();
addresseelogoimage->hide();
}
emit updateQueryChrome(this,getName());
emitUpdateInfo();
}
NickInfoPtr Query::getNickInfo()
{
return m_nickInfo;
}
TQString Query::getTextInLine() { return queryInput->text(); }
bool Query::canBeFrontView() { return true; }
bool Query::searchView() { return true; }
void Query::appendInputText(const TQString& s, bool fromCursor)
{
if(!fromCursor)
{
queryInput->append(s);
}
else
{
int para = 0, index = 0;
queryInput->getCursorPosition(&para, &index);
queryInput->insertAt(s, para, index);
queryInput->setCursorPosition(para, index + s.length());
}
}
// virtual
void Query::setChannelEncoding(const TQString& encoding)
{
Preferences::setChannelEncoding(m_server->getDisplayName(), getName(), encoding);
}
TQString Query::getChannelEncoding() // virtual
{
return Preferences::channelEncoding(m_server->getDisplayName(), getName());
}
TQString Query::getChannelEncodingDefaultDesc() // virtual
{
return i18n("Identity Default ( %1 )").arg(getServer()->getIdentity()->getCodecName());
}
bool Query::closeYourself(bool confirm)
{
int result = KMessageBox::Continue;
if (confirm)
result=KMessageBox::warningContinueCancel(this, i18n("Do you want to close your query with %1?").arg(getName()), i18n("Close Query"), i18n("Close"), "QuitQueryTab");
if (result == KMessageBox::Continue)
{
m_server->removeQuery(this);
return true;
}
return false;
}
void Query::closeWithoutAsking()
{
m_server->removeQuery(this);
}
void Query::filesDropped(const TQStrList& files)
{
m_server->sendURIs(files,getName());
}
void Query::serverOnline(bool online)
{
//queryInput->setEnabled(online);
getTextView()->setNickAndChannelContextMenusEnabled(online);
TQPopupMenu* popup = getTextView()->getPopup();
if (popup)
{
popup->setItemEnabled(Konversation::Whois, online);
popup->setItemEnabled(Konversation::Version, online);
popup->setItemEnabled(Konversation::Ping, online);
popup->setItemEnabled(Konversation::IgnoreNick, online);
popup->setItemEnabled(Konversation::UnignoreNick, online);
popup->setItemEnabled(Konversation::AddNotify, online);
if (kapp->authorize("allow_downloading"))
popup->setItemEnabled(Konversation::DccSend, online);
}
}
void Query::emitUpdateInfo()
{
TQString info;
if(m_nickInfo->loweredNickname() == m_server->loweredNickname())
info = i18n("Talking to yourself");
else if(m_nickInfo)
info = m_nickInfo->getBestAddresseeName();
else
info = getName();
emit updateInfo(info);
}
// show quit message of nick if we see it
void Query::quitNick(const TQString& reason)
{
TQString displayReason = reason;
if (displayReason.isEmpty())
{
appendCommandMessage(i18n("Quit"),i18n("%1 has left this server.").arg(getName()),false);
}
else
{
if (displayReason.find(TQRegExp("[\\0000-\\0037]"))!=-1)
displayReason+="\017";
appendCommandMessage(i18n("Quit"),i18n("%1 has left this server (%2).").arg(getName()).arg(displayReason),false);
}
}
#include "query.moc"