/* 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 Copyright (C) 2006-2008 Eike Hein */ #include "topiclabel.h" #include "konversationapplication.h" #include "connectionmanager.h" #include "server.h" #include "common.h" #include "channel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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("editcopy"),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(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()); KProcess *proc = new KProcess; 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(KProcess::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 KPopupMenu(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, "" + TQStyleSheet::escape(m_fullText) + ""); } else { setWordWrap(WidgetWidth); if(height() < contentsHeight()) { TQToolTip::add(this, "" + TQStyleSheet::escape(m_fullText) + ""); } } KActiveLabel::setText("" + text + ""); } 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("" + text + "", 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("editcopy"), 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"