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.
386 lines
12 KiB
386 lines
12 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) 2004 Peter Simonsson <psn@linux.se>
|
|
Copyright (C) 2006-2008 Eike Hein <hein@kde.org>
|
|
*/
|
|
|
|
#include "topiclabel.h"
|
|
#include "konversationapplication.h"
|
|
#include "connectionmanager.h"
|
|
#include "server.h"
|
|
#include "common.h"
|
|
#include "channel.h"
|
|
|
|
#include <tqsimplerichtext.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqclipboard.h>
|
|
|
|
#include <krun.h>
|
|
#include <kprocess.h>
|
|
#include <kshell.h>
|
|
#include <kurldrag.h>
|
|
#include <kstringhandler.h>
|
|
#include <tdeglobal.h>
|
|
#include <kdebug.h>
|
|
#include <tdepopupmenu.h>
|
|
#include <kiconloader.h>
|
|
#include <kbookmarkmanager.h>
|
|
#include <tdeversion.h>
|
|
|
|
|
|
namespace Konversation
|
|
{
|
|
|
|
TopicLabel::TopicLabel(TQWidget *parent, const char *name)
|
|
: KActiveLabel(parent, name)
|
|
{
|
|
setWrapPolicy(TQTextEdit::AtWordOrDocumentBoundary);
|
|
setFocusPolicy(TQ_ClickFocus);
|
|
|
|
m_isOnChannel = false;
|
|
m_copyUrlMenu = false;
|
|
mousePressed=false;
|
|
|
|
m_popup = new TQPopupMenu(this,"topiclabel_context_menu");
|
|
m_popup->insertItem(SmallIconSet("edit-copy"),i18n("&Copy"),Copy);
|
|
m_popup->insertItem(i18n("Select All"),SelectAll);
|
|
|
|
setupChannelPopupMenu();
|
|
|
|
connect(this, TQT_SIGNAL(highlighted(const TQString&)), this, TQT_SLOT(highlightedSlot(const TQString&)));
|
|
}
|
|
|
|
TopicLabel::~TopicLabel()
|
|
{
|
|
}
|
|
|
|
TQSize TopicLabel::minimumSizeHint() const
|
|
{
|
|
int minHeight = fontMetrics().lineSpacing() + fontMetrics().descent();
|
|
return TQSize(0, minHeight);
|
|
}
|
|
|
|
TQSize TopicLabel::sizeHint() const
|
|
{
|
|
int minHeight = fontMetrics().lineSpacing() + fontMetrics().descent();
|
|
return TQSize(0, minHeight);
|
|
}
|
|
|
|
void TopicLabel::setServer(Server* server)
|
|
{
|
|
m_server = server;
|
|
}
|
|
|
|
void TopicLabel::contentsMousePressEvent(TQMouseEvent *e)
|
|
{
|
|
if (e->button()==Qt::LeftButton)
|
|
{
|
|
pressPosition=e->pos();
|
|
urlToDrag = anchorAt(pressPosition);
|
|
// HACK Replace % with \x03 in the url to keep TQt from doing stupid things
|
|
urlToDrag = urlToDrag.replace ('\x03', "%");
|
|
// Hack to counter the fact that we're given an decoded url
|
|
urlToDrag = KURL::fromPathOrURL(urlToDrag).url();
|
|
if (!urlToDrag.isNull())
|
|
{
|
|
mousePressed=true;
|
|
return;
|
|
}
|
|
}
|
|
KActiveLabel::contentsMousePressEvent(e);
|
|
}
|
|
|
|
void TopicLabel::contentsMouseReleaseEvent(TQMouseEvent *e)
|
|
{
|
|
if (e->button()==Qt::LeftButton)
|
|
{
|
|
if (mousePressed) openLink(urlToDrag);
|
|
mousePressed=false;
|
|
}
|
|
KActiveLabel::contentsMouseReleaseEvent(e);
|
|
}
|
|
|
|
void TopicLabel::contentsMouseMoveEvent(TQMouseEvent *e)
|
|
{
|
|
if (mousePressed && (pressPosition-e->pos()).manhattanLength() > TQApplication::startDragDistance())
|
|
{
|
|
mousePressed=false;
|
|
removeSelection();
|
|
KURL ux = KURL::fromPathOrURL(urlToDrag);
|
|
//FIXME consistent IRC URL serialization
|
|
if (urlToDrag.startsWith("##")) ux=TQString("irc://%1:%2/%3").arg(m_server->getServerName()).
|
|
arg(m_server->getPort()).arg(urlToDrag.mid(2));
|
|
KURLDrag* u=new KURLDrag(ux,viewport());
|
|
u->drag();
|
|
}
|
|
KActiveLabel::contentsMouseMoveEvent(e);
|
|
}
|
|
|
|
void TopicLabel::leaveEvent(TQEvent*)
|
|
{
|
|
emit clearStatusBarTempText();
|
|
m_lastStatusText = TQString();
|
|
}
|
|
|
|
void TopicLabel::openLink(const TQString& link)
|
|
{
|
|
if (!link.isEmpty())
|
|
{
|
|
if (link.startsWith("irc://"))
|
|
{
|
|
KonversationApplication* konvApp = static_cast<KonversationApplication*>(kapp);
|
|
konvApp->getConnectionManager()->connectTo(Konversation::SilentlyReuseConnection, link);
|
|
}
|
|
else if (link.startsWith("#") && m_server && m_server->isConnected())
|
|
{
|
|
TQString channel(link);
|
|
channel.replace("##","#");
|
|
m_server->sendJoinCommand(channel);
|
|
}
|
|
// Always use KDE default mailer.
|
|
else if (!Preferences::useCustomBrowser() || link.lower().startsWith("mailto:"))
|
|
{
|
|
new KRun(KURL::fromPathOrURL(link));
|
|
}
|
|
else
|
|
{
|
|
TQString cmd = Preferences::webBrowserCmd();
|
|
cmd.replace("%u",KURL::fromPathOrURL(link).url());
|
|
TDEProcess *proc = new TDEProcess;
|
|
TQStringList cmdAndArgs = KShell::splitArgs(cmd);
|
|
*proc << cmdAndArgs;
|
|
// This code will also work, but starts an extra shell process.
|
|
// kdDebug() << "IRCView::linkClickSlot(): cmd = " << cmd << endl;
|
|
// *proc << cmd;
|
|
// proc->setUseShell(true);
|
|
proc->start(TDEProcess::DontCare);
|
|
delete proc;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TopicLabel::contentsContextMenuEvent(TQContextMenuEvent* ev)
|
|
{
|
|
bool block = contextMenu(ev);
|
|
|
|
if(!block)
|
|
{
|
|
KActiveLabel::contentsContextMenuEvent(ev);
|
|
}
|
|
}
|
|
|
|
bool TopicLabel::contextMenu(TQContextMenuEvent* ce)
|
|
{
|
|
if (m_isOnChannel)
|
|
{
|
|
m_channelPopup->exec(ce->globalPos());
|
|
m_isOnChannel = false;
|
|
}
|
|
else
|
|
{
|
|
m_popup->setItemEnabled(Copy,(hasSelectedText()));
|
|
|
|
int r = m_popup->exec(ce->globalPos());
|
|
|
|
switch(r)
|
|
{
|
|
case -1:
|
|
// dummy. -1 means, no entry selected. we don't want -1to go in default, so
|
|
// we catch it here
|
|
break;
|
|
case Copy:
|
|
copy();
|
|
break;
|
|
case CopyUrl:
|
|
{
|
|
TQClipboard *cb = TDEApplication::kApplication()->clipboard();
|
|
cb->setText(m_urlToCopy,TQClipboard::Selection);
|
|
cb->setText(m_urlToCopy,TQClipboard::Clipboard);
|
|
break;
|
|
}
|
|
case SelectAll:
|
|
selectAll();
|
|
break;
|
|
case Bookmark:
|
|
{
|
|
KBookmarkManager* bm = KBookmarkManager::userBookmarksManager();
|
|
KBookmarkGroup bg = bm->addBookmarkDialog(m_urlToCopy, TQString());
|
|
bm->save();
|
|
bm->emitChanged(bg);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void TopicLabel::setupChannelPopupMenu()
|
|
{
|
|
m_channelPopup = new TDEPopupMenu(this,"channel_context_menu");
|
|
m_channelPopupId = m_channelPopup->insertTitle(m_currentChannel);
|
|
m_channelPopup->insertItem(i18n("&Join"),Konversation::Join);
|
|
m_channelPopup->insertItem(i18n("Get &user list"),Konversation::Names);
|
|
m_channelPopup->insertItem(i18n("Get &topic"),Konversation::Topic);
|
|
|
|
connect(m_channelPopup, TQT_SIGNAL(activated(int)), this, TQT_SIGNAL(popupCommand(int)));
|
|
}
|
|
|
|
void TopicLabel::setText(const TQString& text)
|
|
{
|
|
m_fullText = text;
|
|
updateSqueezedText();
|
|
}
|
|
|
|
void TopicLabel::updateSqueezedText()
|
|
{
|
|
TQToolTip::remove(this);
|
|
|
|
if (m_fullText.isEmpty())
|
|
{
|
|
KActiveLabel::setText(TQString());
|
|
|
|
return;
|
|
}
|
|
|
|
TQFontMetrics fm(currentFont());
|
|
TQString text = m_fullText;
|
|
// text.replace("&", "&"). Not needed as we do it in tagURLs
|
|
text.replace("<", "\x0blt;"). // tagUrls will replace \x0b with &
|
|
replace(">", "\x0bgt;");
|
|
text = tagURLs(text, "", false);
|
|
|
|
if(height() < (fm.lineSpacing() * 2))
|
|
{
|
|
text = rPixelSqueeze(text, visibleWidth() - 10);
|
|
setWordWrap(NoWrap);
|
|
TQToolTip::add(this, "<qt>" + TQStyleSheet::escape(m_fullText) + "</qt>");
|
|
}
|
|
else
|
|
{
|
|
setWordWrap(WidgetWidth);
|
|
|
|
if(height() < contentsHeight())
|
|
{
|
|
TQToolTip::add(this, "<qt>" + TQStyleSheet::escape(m_fullText) + "</qt>");
|
|
}
|
|
}
|
|
|
|
KActiveLabel::setText("<qt>" + text + "</qt>");
|
|
}
|
|
|
|
void TopicLabel::resizeEvent(TQResizeEvent* ev)
|
|
{
|
|
KActiveLabel::resizeEvent(ev);
|
|
updateSqueezedText();
|
|
}
|
|
|
|
TQString TopicLabel::rPixelSqueeze(const TQString& text, uint maxPixels)
|
|
{
|
|
TQFontMetrics fm(currentFont());
|
|
uint tw = textWidth(text, fm);
|
|
|
|
if(tw > maxPixels)
|
|
{
|
|
TQString tmp = text;
|
|
const uint em = fm.maxWidth();
|
|
maxPixels -= fm.width("...");
|
|
int len, delta;
|
|
|
|
while((tw > maxPixels) && !tmp.isEmpty())
|
|
{
|
|
len = tmp.length();
|
|
delta = (tw - maxPixels) / em;
|
|
delta = kClamp(delta, 1, len);
|
|
|
|
tmp.remove(len - delta, delta);
|
|
tw = textWidth(tmp, fm);
|
|
}
|
|
|
|
return tmp.append("...");
|
|
}
|
|
|
|
return text;
|
|
}
|
|
|
|
uint TopicLabel::textWidth(const TQString& text, const TQFontMetrics& fm)
|
|
{
|
|
TQSimpleRichText richText("<qt>" + text + "</qt>", currentFont());
|
|
richText.setWidth(fm.width(text));
|
|
|
|
return richText.widthUsed();
|
|
}
|
|
|
|
void TopicLabel::highlightedSlot(const TQString& _link)
|
|
{
|
|
TQString link = KURL::fromPathOrURL(_link).url();
|
|
//we just saw this a second ago. no need to reemit.
|
|
if (link == m_lastStatusText && !link.isEmpty())
|
|
return;
|
|
|
|
// remember current URL to overcome link clicking problems in TQTextBrowser
|
|
m_highlightedURL = link;
|
|
|
|
if (link.isEmpty())
|
|
{
|
|
if (!m_lastStatusText.isEmpty())
|
|
{
|
|
emit clearStatusBarTempText();
|
|
m_lastStatusText = TQString();
|
|
}
|
|
} else {
|
|
m_lastStatusText = link;
|
|
}
|
|
|
|
if (!link.startsWith("#"))
|
|
{
|
|
m_isOnChannel = false;
|
|
|
|
if (!link.isEmpty()) {
|
|
//link therefore != m_lastStatusText so emit with this new text
|
|
emit setStatusBarTempText(link);
|
|
}
|
|
if (link.isEmpty() && m_copyUrlMenu)
|
|
{
|
|
m_popup->removeItem(CopyUrl);
|
|
m_popup->removeItem(Bookmark);
|
|
m_copyUrlMenu = false;
|
|
}
|
|
else if (!link.isEmpty() && !m_copyUrlMenu)
|
|
{
|
|
m_popup->insertItem(SmallIcon("edit-copy"), i18n("Copy URL to Clipboard"), CopyUrl, 0);
|
|
m_popup->insertItem(SmallIcon("bookmark"), i18n("Add to Bookmarks"), Bookmark, 1);
|
|
m_copyUrlMenu = true;
|
|
m_urlToCopy = link;
|
|
}
|
|
}
|
|
else if (link.startsWith("##"))
|
|
{
|
|
m_currentChannel = link.mid(1);
|
|
|
|
emit currentChannelChanged(m_currentChannel);
|
|
|
|
TQString prettyId = m_currentChannel;
|
|
|
|
if (prettyId.length()>15)
|
|
{
|
|
prettyId.truncate(15);
|
|
prettyId.append("...");
|
|
}
|
|
|
|
m_channelPopup->changeTitle(m_channelPopupId,prettyId);
|
|
m_isOnChannel = true;
|
|
emit setStatusBarTempText(i18n("Join the channel %1").arg(m_currentChannel));
|
|
}
|
|
}
|
|
}
|
|
|
|
#include "topiclabel.moc"
|