diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d7af35d..7ad84e7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,83 +1,82 @@ project(konversation) cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) set (QT_MIN_VERSION "5.3.0") set(KF5_MIN_VERSION "5.15.0") find_package(ECM 1.2.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(CheckIncludeFile) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(FeatureSummary) find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core Widgets) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED Archive Bookmarks Config ConfigWidgets CoreAddons Crash DocTools Emoticons I18n IdleTime NotifyConfig KIO Parts Solid - Sonnet Wallet WidgetsAddons GlobalAccel DBusAddons Notifications WindowSystem IconThemes ItemViews ) find_package(Phonon4Qt5 4.6.60 REQUIRED) include_directories(${PHONON_INCLUDES}) find_package(Qca-qt5 2.1.0) set_package_properties(Qca-qt5 PROPERTIES DESCRIPTION "Support for encryption" URL "http://download.kde.org/stable/qca-qt5/" TYPE OPTIONAL) check_include_file("stropts.h" HAVE_STROPTS_H) check_include_file("byteswap.h" HAVE_BYTESWAP_H) check_include_file("sys/endian.h" HAVE_SYS_ENDIAN_H) set(HAVE_QCA2 ${Qca-qt5_FOUND}) configure_file(config-konversation.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-konversation.h ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_definitions( -DQT_USE_QSTRINGBUILDER -DQT_NO_CAST_TO_ASCII -DQT_STRICT_ITERATORS -DQT_NO_URL_CAST_FROM_STRING -DQT_NO_CAST_FROM_BYTEARRAY # -DQT_NO_SIGNALS_SLOTS_KEYWORDS FIXME KF5 Port: QCA includes cause trouble. -DQT_USE_FAST_OPERATOR_PLUS ) add_subdirectory(src) add_subdirectory(data) add_subdirectory(doc) ki18n_install(po) get_filename_component(_doc_translations_path doc-translations ABSOLUTE) if (EXISTS ${_doc_translations_path}/CMakeLists.txt) add_subdirectory(doc-translations) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f808bb9a..1cf7cfbe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,243 +1,242 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config) include_directories(config dcc irc viewer upnp) set(core_SRCS #==================================== #=== Application config/preferences.cpp application.cpp dbus.cpp mainwindow.cpp main.cpp common.cpp sound.cpp ssllabel.cpp statusbar.cpp bookmarkhandler.cpp scriptlauncher.cpp konsolepanel.cpp notificationhandler.cpp awaymanager.cpp connectionmanager.cpp connectionsettings.cpp identity.cpp identitydialog.cpp #=== GUI urlcatcher.cpp queuetuner.cpp quickconnectdialog.cpp ) set (irc_SRCS #== IRC irc/server.cpp irc/query.cpp irc/channel.cpp irc/channellistpanel.cpp irc/channelnick.cpp irc/modebutton.cpp irc/joinchanneldialog.cpp irc/invitedialog.cpp irc/topichistorymodel.cpp irc/irccharsets.cpp irc/nick.cpp irc/nickinfo.cpp irc/nicklistview.cpp irc/nicksonline.cpp irc/nicksonlineitem.cpp #=== Server irc/inputfilter.cpp irc/outputfilter.cpp irc/outputfilterresolvejob.cpp irc/ircqueue.cpp irc/servergroupdialog.cpp irc/servergroupsettings.cpp irc/serverison.cpp irc/serverlistdialog.cpp irc/serverlistview.cpp irc/serversettings.cpp ) ki18n_wrap_ui(irc_SRCS irc/channellistpanelui.ui irc/channeldialogui.ui irc/joinchannelui.ui irc/serverdialogui.ui irc/servergroupdialogui.ui irc/serverlistdialogui.ui irc/invitedialog.ui ) #=== Configuration dialog pages set(config_SRCS config/configdialog.cpp config/settingsdialog.cpp config/alias_config.cpp config/autoreplace_config.cpp config/dcc_config.cpp config/highlight_config.cpp config/ignore_config.cpp config/nicklistbehavior_config.cpp config/osd_config.cpp config/tabs_config.cpp config/theme_config.cpp config/quickbuttons_config.cpp config/warnings_config.cpp config/connectionbehavior_config.cpp ) ki18n_wrap_ui(config_SRCS config/alias_configui.ui config/autoreplace_configui.ui config/chatwindowappearance_config.ui config/chatwindowbehaviour_config.ui config/colorsappearance_config.ui config/connectionbehavior_config.ui config/dcc_configui.ui config/fontappearance_config.ui config/generalbehavior_configui.ui config/highlight_configui.ui config/ignore_configui.ui config/log_config.ui config/nicklistbehavior_configui.ui config/osd_configui.ui config/quickbuttons_configui.ui config/tabnotifications_config.ui config/tabs_configui.ui config/theme_configui.ui config/warnings_configui.ui config/watchednicknames_configui.ui ) #=== Viewer set(viewer_SRCS viewer/ircinput.cpp viewer/ircview.cpp viewer/chatwindow.cpp viewer/rawlog.cpp viewer/statuspanel.cpp viewer/ircviewbox.cpp viewer/viewcontainer.cpp viewer/pasteeditor.cpp viewer/highlight.cpp viewer/highlightviewitem.cpp viewer/ignore.cpp viewer/ignorelistviewitem.cpp viewer/irccolorchooser.cpp viewer/logfilereader.cpp viewer/insertchardialog.cpp viewer/osd.cpp viewer/topiclabel.cpp viewer/awaylabel.cpp viewer/editnotifydialog.cpp viewer/emoticons.cpp viewer/images.cpp viewer/quickbutton.cpp viewer/searchbar.cpp viewer/irccontextmenus.cpp viewer/trayicon.cpp viewer/viewspringloader.cpp viewer/channeloptionsdialog.cpp viewer/topicedit.cpp viewer/topichistoryview.cpp viewer/viewtree.cpp ) ki18n_wrap_ui(viewer_SRCS viewer/channeloptionsui.ui viewer/irccolorchooserui.ui viewer/pasteeditor.ui ) #=== DCC set(dcc_SRCS dcc/chat.cpp dcc/chatcontainer.cpp dcc/dcccommon.cpp dcc/dccfiledialog.cpp dcc/recipientdialog.cpp dcc/resumedialog.cpp dcc/transfer.cpp dcc/transferdetailedinfopanel.cpp dcc/transfermanager.cpp dcc/transferpanel.cpp dcc/transferrecv.cpp dcc/transfersend.cpp dcc/transferlistmodel.cpp dcc/transferview.cpp dcc/whiteboard.cpp dcc/whiteboardcolorchooser.cpp dcc/whiteboardfontchooser.cpp dcc/whiteboardglobals.cpp dcc/whiteboardpaintarea.cpp dcc/whiteboardtoolbar.cpp ) ki18n_wrap_ui(dcc_SRCS dcc/transferdetailedinfopanelui.ui dcc/transferdetailedtimeinfopanelui.ui dcc/whiteboardtoolbarui.ui dcc/whiteboardfontchooserui.ui ) if (Qca-qt5_FOUND) set(cipher_SRCS cipher.cpp) endif (Qca-qt5_FOUND) set(upnp_SRCS upnp/soap.cpp upnp/upnpdescriptionparser.cpp upnp/upnpmcastsocket.cpp upnp/upnprouter.cpp ) set (completed_SRCS ${core_SRCS} ${irc_SRCS} ${viewer_SRCS} ${config_SRCS} ${cipher_SRCS} ${upnp_SRCS} ${dcc_SRCS}) set (konversation_SRCS ${completed_SRCS}) ki18n_wrap_ui(konversation_SRCS identitydialog.ui queuetunerbase.ui viewer/searchbarbase.ui ) kconfig_add_kcfg_files(konversation_SRCS config/preferences_base.kcfgc) add_executable(konversation ${konversation_SRCS}) target_link_libraries(konversation Qt5::Widgets KF5::Archive KF5::Bookmarks KF5::ConfigWidgets KF5::Crash KF5::Emoticons KF5::I18n KF5::IdleTime KF5::NotifyConfig KF5::KIOFileWidgets KF5::KIOWidgets KF5::Parts KF5::Solid - KF5::SonnetCore KF5::Wallet KF5::WidgetsAddons KF5::GlobalAccel KF5::DBusAddons KF5::CoreAddons KF5::Notifications KF5::WindowSystem KF5::IconThemes KF5::ItemViews Phonon::phonon4qt5) if (Qca-qt5_FOUND) target_link_libraries(konversation qca-qt5) endif () install(TARGETS konversation ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/viewer/ircinput.cpp b/src/viewer/ircinput.cpp index fa612911..ef729e02 100644 --- a/src/viewer/ircinput.cpp +++ b/src/viewer/ircinput.cpp @@ -1,573 +1,569 @@ /* 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. */ /* The line input widget with chat enhanced functions begin: Tue Mar 5 2002 copyright: (C) 2002 by Dario Abatianni email: eisfuchs@tigress.com */ #include "ircinput.h" #include "application.h" #include "pasteeditor.h" #include #include #include #include #include #include #include -#include - #define MAXHISTORY 100 -Sonnet::Speller* IRCInput::m_speller = 0; - IRCInput::IRCInput(QWidget* parent) : KTextEdit(parent) { enableFindReplace(false); setAcceptRichText(false); //I am not terribly interested in finding out where this value comes from //nor in compensating for it if my guess is incorrect. so, cache it. m_qtBoxPadding = document()->size().toSize().height() - fontMetrics().lineSpacing(); connect(qApp, SIGNAL(appearanceChanged()), this, SLOT(updateAppearance())); m_multiRow = Preferences::self()->useMultiRowInputBox(); // add one empty line to the history (will be overwritten with newest entry) historyList.prepend(QString()); // reset history line counter lineNum=0; // reset completion mode setCompletionMode('\0'); completionBox = new KCompletionBox(this); connect(completionBox, &KCompletionBox::activated, this, &IRCInput::insertCompletion); // widget may not be resized vertically setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Fixed)); updateAppearance(); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setWhatsThis(i18n("

The input line is where you type messages to be sent the channel, query, or server. A message sent to a channel is seen by everyone on the channel, whereas a message in a query is sent only to the person in the query with you.

To automatically complete the nickname you began typing, press Tab. If you have not begun typing, the last successfully completed nickname will be used.

You can also send special commands:

/me actionshows up as an action in the channel or query. For example: /me sings a song will show up in the channel as 'Nick sings a song'.
/whois nicknameshows information about this person, including what channels they are in.

For more commands, see the Konversation Handbook.

A message cannot contain multiple lines.

")); m_disableSpellCheckTimer = new QTimer(this); connect(m_disableSpellCheckTimer, &QTimer::timeout, this, &IRCInput::disableSpellChecking); document()->adjustSize(); document()->setDocumentMargin(2); } IRCInput::~IRCInput() { } void IRCInput::createHighlighter() { KTextEdit::createHighlighter(); setSpellCheckingLanguage(spellCheckingLanguage()); } QSize IRCInput::sizeHint() const { QFontMetrics fm(font()); int h = document()->size().toSize().height() - fm.descent() + 2 * frameWidth(); QStyleOptionFrameV2 opt; opt.initFrom(this); opt.rect = QRect(0, 0, 100, h); opt.lineWidth = lineWidth(); opt.midLineWidth = 0; opt.state |= QStyle::State_Sunken; QSize s = style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(100, h).expandedTo(QApplication::globalStrut()), this); return s; } QSize IRCInput::minimumSizeHint() const { return sizeHint(); } void IRCInput::maybeResize() { updateGeometry(); } void IRCInput::showEvent(QShowEvent* /* e */) { m_disableSpellCheckTimer->stop(); setCheckSpellingEnabled(Preferences::self()->spellChecking()); setSpellCheckingLanguage(spellCheckingLanguage()); connect(this, &IRCInput::checkSpellingChanged, this, &IRCInput::setSpellChecking); } void IRCInput::hideEvent(QHideEvent* /* event */) { // If we disable spell-checking here immediately, tab switching will // be very slow. If we delay it by five seconds, a user would have to // need more than five seconds to switch between all his tabs before // the slowdown starts to occur (show event stops the timer, i.e. wrap- // around is not an issue). Unless he has unlikely amounts of channels, // needing more than five seconds indicates very slow switching speed, // which makes the delay a non-issue to begin with. Hence this fixes // the problem on the surface. In the KDE 4 version, we want to look // into having only one spell-checker instance instead of starting and // stopping at all. //TODO FIXME when we get to require 4.2 the above is possible with //KTextEditSpellInterface and is actually quite easy to do. disconnect(SIGNAL(checkSpellingChanged(bool))); m_disableSpellCheckTimer->setSingleShot(true); m_disableSpellCheckTimer->start(5000); } void IRCInput::resizeEvent(QResizeEvent* e) { maybeResize(); KTextEdit::resizeEvent(e); } void IRCInput::disableSpellChecking() { setCheckSpellingEnabled(false); } void IRCInput::setSpellChecking(bool set) { Preferences::self()->setSpellChecking(set); } void IRCInput::updateAppearance() { QPalette palette; if (Preferences::self()->inputFieldsBackgroundColor()) { palette.setColor(QPalette::Text, Preferences::self()->color(Preferences::ChannelMessage)); palette.setColor(QPalette::Base, Preferences::self()->color(Preferences::TextViewBackground)); } setPalette(palette); if (Preferences::self()->customTextFont()) setFont(Preferences::self()->textFont()); else setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont)); m_multiRow = Preferences::self()->useMultiRowInputBox(); setLineWrapMode(m_multiRow ? WidgetWidth : NoWrap); if (m_multiRow) connect(this, &IRCInput::textChanged, this, &IRCInput::maybeResize); else disconnect(this, &IRCInput::textChanged, this, &IRCInput::maybeResize); maybeResize(); ensureCursorVisible(); //appears to trigger updateGeometry } void IRCInput::setText(const QString& text, bool preserveContents) { if (!text.isEmpty() && preserveContents) getHistory(false); // reimplemented to set cursor at the end of the new text KTextEdit::setPlainText(text); moveCursor(QTextCursor::End); } // FIXME - find a better way to do this. eventfilters introduce nebulous behaviour //take text events from IRCView and TopicLabel bool IRCInput::eventFilter(QObject *object,QEvent *event) { if (object->metaObject()->className() == QString("IRCView") || object->metaObject()->className() == QString("Konversation::TopicLabel")) { if (event->type() == QEvent::KeyPress) { QKeyEvent* ke = static_cast(event); // Allow tab to be handled naturally by the widget. // Once it runs out of links it goes to the next control. if (ke->key() == Qt::Key_Tab && (ke->modifiers() == 0 || ke->modifiers() == Qt::ShiftModifier)) return false; if (!ke->text().isEmpty() && ((ke->modifiers() & (Qt::ShiftModifier|Qt::KeypadModifier|Qt::GroupSwitchModifier)) || ke->modifiers() == 0)) { setFocus(); Application::sendEvent(this,event); return true; } } } return KTextEdit::eventFilter(object,event); } // Take care of Tab, Cursor and so on void IRCInput::keyPressEvent(QKeyEvent* e) { switch(e->key()) { case Qt::Key_Tab: emit nickCompletion(); return; break; case Qt::Key_Up: if (m_multiRow && textCursor().movePosition(QTextCursor::Up)) break; getHistory(true); return; break; case Qt::Key_Down: if (m_multiRow && textCursor().movePosition(QTextCursor::Down)) break; getHistory(false); return; break; case Qt::Key_Enter: case Qt::Key_Return: { if(!toPlainText().isEmpty()) addHistory(toPlainText()); if(completionBox->isHidden()) { // Reset completion mode setCompletionMode('\0'); // Ctrl+Enter is a special case in which commands should be send as normal messages if ( e->modifiers() & Qt::ControlModifier ) { emit envelopeCommand(); } else { setText(Application::instance()->doAutoreplace(toPlainText(), true).first); emit submit(); } } else { insertCompletion(completionBox->currentItem() ? completionBox->currentItem()->text() : completionBox->item(0)->text()); completionBox->hide(); } // prevent widget from adding lines return; } break; default: // Check if the keystroke actually produced text. If not it was just a qualifier. if(!e->text().isEmpty() || ((e->key() >= Qt::Key_Home) && (e->key() <= Qt::Key_Down))) { if(getCompletionMode()!='\0') { setCompletionMode('\0'); emit endCompletion(); } completionBox->hide(); } // support ASCII BEL if(e->text().unicode()->toLatin1() == 7) insertPlainText("%G"); // support ^U (delete text in input box) else if(e->text().unicode()->toLatin1() == 21) setText(QString()); } KTextEdit::keyPressEvent(e); } bool IRCInput::event(QEvent* e) { if (e->type() == QEvent::ShortcutOverride) { // Make sure KTextEdit doesn't eat actionCollection shortcuts QKeyEvent* event = static_cast(e); const int key = event->key() | event->modifiers(); foreach(QAction* action, Application::instance()->getMainWindow()->actionCollection()->actions()) { if (action->shortcuts().contains(QKeySequence(key))) { event->ignore(); return false; } } } return KTextEdit::event(e); } void IRCInput::wheelEvent(QWheelEvent* e) { if (e->delta() > 0) getHistory(true); else if (e->delta() < 0) getHistory(false); KTextEdit::wheelEvent(e); } void IRCInput::addHistory(const QString& line) { // Only add line if it's not the same as the last was if(historyList.value(1)!=line) { // Replace empty first entry with line historyList[0]=line; // Add new empty entry to history historyList.prepend(QString()); // Remove oldest line in history, if the list grows beyond MAXHISTORY if(historyList.count()>MAXHISTORY) historyList.removeLast(); } // Reset history counter lineNum=0; } void IRCInput::getHistory(bool up) { // preserve text historyList[lineNum]=toPlainText(); // Did the user press cursor up? if(up) { // increment the line counter lineNum++; // if we are past the end of the list, go to the last entry if (lineNum==historyList.count()) { lineNum--; return; } } // no, it was cursor down else { // If we are at the top of the lest, arrow-down shall add the text to the history and clear the field for new input if(lineNum==0) { if(!toPlainText().isEmpty()) addHistory(toPlainText()); setText(QString()); } // If we aren't at the top of the list, decrement the line counter else { lineNum--; } } // replace the text in the input field with history setText(historyList[lineNum]); } void IRCInput::paste(bool useSelection) { insertFromMimeData(QApplication::clipboard()->mimeData(useSelection ? QClipboard::Selection : QClipboard::Clipboard)); } void IRCInput::insertFromMimeData(const QMimeData * source) { if(!source) return; setFocus(); // Copy text from the clipboard (paste) QString pasteText = source->text(); // is there any text in the clipboard? if(!pasteText.isEmpty()) { //End completion on paste setCompletionMode('\0'); emit endCompletion(); bool signal=false; //filter out crashy crap Konversation::sterilizeUnicode(pasteText); // replace \r with \n to make xterm pastes happy pasteText.replace('\r','\n'); // remove blank lines while(pasteText.contains("\n\n")) pasteText.replace("\n\n","\n"); QRegExp reTopSpace("^ *\n"); while(pasteText.contains(reTopSpace)) pasteText.remove(reTopSpace); QRegExp reBottomSpace("\n *$"); while(pasteText.contains(reBottomSpace)) pasteText.remove(reBottomSpace); // does the text contain at least one newline character? if(pasteText.contains('\n')) { // make comparisons easier (avoid signed / unsigned warnings) int pos=pasteText.indexOf('\n'); int rpos=pasteText.lastIndexOf('\n'); // emit the signal if there's a line break in the middle of the text if(pos>0 && pos!=(pasteText.length()-1)) signal=true; // emit the signal if there's more than one line break in the text if(pos!=rpos) signal=true; // Remove the \n from end of the line if there's only one \n if(!signal) pasteText.remove('\n'); } else { insertPlainText(pasteText); ensureCursorVisible(); return; } // should we signal the application due to newlines in the paste? if(signal) { // if there is text in the input line if(!toPlainText().isEmpty()) { // prepend text to the paste pasteText=toPlainText()+'\n'+pasteText; } // ask the user on long pastes if(checkPaste(pasteText)) { pasteText = Application::instance()->doAutoreplace(pasteText, true).first; Konversation::sterilizeUnicode(pasteText); // signal pasted text emit textPasted(pasteText); // remember old line, in case the user does not paste eventually addHistory(pasteText); // delete input text setText(QString()); } } // otherwise let the KLineEdit handle the pasting else KTextEdit::insertFromMimeData(source); } } bool IRCInput::checkPaste(QString& text) { int doPaste=KMessageBox::Yes; //text is now preconditioned when you get here int lines=text.count('\n'); if(text.length()>256 || lines) { QString bytesString = i18np("1 byte", "%1 bytes", text.length()); QString linesString = i18np("1 line", "%1 lines", lines+1); doPaste=KMessageBox::warningYesNoCancel (this, i18nc( "%1 is, for instance, '200 bytes'. %2 is, for instance, '7 lines'. Both are localised (see the two previous messages).", "You are attempting to paste a large portion of text (%1 or %2) into " "the chat. This can cause connection resets or flood kills. " "Do you really want to continue?", bytesString, linesString), i18n("Large Paste Warning"), KGuiItem(i18n("Paste")), KGuiItem(i18n("&Edit...")), KStandardGuiItem::cancel(), QString("LargePaste"), KMessageBox::Dangerous); } if (doPaste==KMessageBox::No) { QString ret(PasteEditor::edit(this,text)); if (ret.isEmpty()) return false; text=ret; return true; } return (doPaste==KMessageBox::Yes); } void IRCInput::showCompletionList(const QStringList& nicks) { completionBox->setItems(nicks); completionBox->popup(); } void IRCInput::insertCompletion(const QString& nick) { int pos; // = cursorPosition(); int oldPos; // = cursorPosition(); //getCursorPosition(&oldPos,&pos); oldPos=pos=textCursor().position(); QString line = toPlainText(); while(pos && line[pos-1] != ' ') pos--; line.remove(pos, oldPos - pos); // did we find the nick in the middle of the line? if(pos) { QString addMiddle(Preferences::self()->nickCompleteSuffixMiddle()); line.insert(pos, nick + addMiddle); pos += nick.length() + addMiddle.length(); } // no, it was at the beginning else { setLastCompletion(nick); QString addStart(Preferences::self()->nickCompleteSuffixStart()); line.insert(pos, nick + addStart); pos += nick.length() + addStart.length(); } setText(line); textCursor().setPosition(pos); } void IRCInput::setLastCompletion(const QString& completion) { m_lastCompletion = completion; } void IRCInput::doInlineAutoreplace() { Application::instance()->doInlineAutoreplace(this); } // Accessor methods void IRCInput::setCompletionMode(char mode) { completionMode=mode; } char IRCInput::getCompletionMode() { return completionMode; } void IRCInput::setOldCursorPosition(int pos) { oldPos=pos; } int IRCInput::getOldCursorPosition() { return oldPos; } diff --git a/src/viewer/ircinput.h b/src/viewer/ircinput.h index 71f98960..b8954b48 100644 --- a/src/viewer/ircinput.h +++ b/src/viewer/ircinput.h @@ -1,97 +1,91 @@ /* 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. */ /* The line input widget with chat enhanced functions begin: Tue Mar 5 2002 copyright: (C) 2002 by Dario Abatianni email: eisfuchs@tigress.com */ #ifndef IRCINPUT_H #define IRCINPUT_H #include -namespace Sonnet -{ - class Speller; -} - class KCompletionBox; class IRCInput : public KTextEdit { Q_OBJECT public: explicit IRCInput(QWidget* parent); ~IRCInput(); void setCompletionMode(char mode); char getCompletionMode(); void setOldCursorPosition(int pos); int getOldCursorPosition(); QString lastCompletion() const { return m_lastCompletion; } void doInlineAutoreplace(); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; virtual bool event(QEvent* e); virtual void createHighlighter(); Q_SIGNALS: void nickCompletion(); void endCompletion(); // tell channel that completion phase is over void textPasted(const QString& text); void submit(); void envelopeCommand(); public Q_SLOTS: void paste(bool useSelection); void showCompletionList(const QStringList& nicks); void setText(const QString& text, bool preserveContents = false); void setLastCompletion(const QString& completion); virtual void setOverwriteMode(bool) { } virtual void updateAppearance(); protected Q_SLOTS: void getHistory(bool up); void insertCompletion(const QString& nick); void disableSpellChecking(); void setSpellChecking(bool set); void maybeResize(); protected: bool eventFilter(QObject *object,QEvent *event); void addHistory(const QString& text); bool checkPaste(QString& text); virtual void insertFromMimeData(const QMimeData *source); virtual void keyPressEvent(QKeyEvent* e); virtual void wheelEvent(QWheelEvent* e); virtual void showEvent(QShowEvent* e); virtual void hideEvent(QHideEvent* e); virtual void resizeEvent(QResizeEvent* e); QStringList historyList; int lineNum; int oldPos; char completionMode; KCompletionBox* completionBox; QString m_lastCompletion; bool m_multiRow; int m_qtBoxPadding; //see comment in constructor QTimer* m_disableSpellCheckTimer; - static Sonnet::Speller* m_speller; }; #endif