diff -rN -u old-psi2/options/default.xml new-psi2/options/default.xml --- old-psi2/options/default.xml 2007-01-25 22:54:08.109375000 +0100 +++ new-psi2/options/default.xml 2007-01-25 22:54:43.328125000 +0100 @@ -136,6 +136,11 @@ Ctrl+PgUp Ctrl+PgDown Ctrl+F + + F3 + Ctrl+Down + + Ctrl+Up Return Enter diff -rN -u old-psi2/src/chatdlg.cpp new-psi2/src/chatdlg.cpp --- old-psi2/src/chatdlg.cpp 2007-01-25 22:54:09.796875000 +0100 +++ new-psi2/src/chatdlg.cpp 2007-01-25 22:54:46.031250000 +0100 @@ -72,6 +72,7 @@ #include "shortcutmanager.h" #include "psicontactlist.h" #include "accountlabel.h" +#include "typeaheadfind.h" #ifdef Q_WS_WIN #include @@ -107,7 +108,8 @@ QMenu *pm_settings; QToolBar *toolbar; - IconAction *act_clear, *act_history, *act_info, *act_pgp, *act_icon, *act_file, *act_compact, *act_voice; + TypeAheadFindBar *typeahead; + IconAction *act_clear, *act_history, *act_info, *act_pgp, *act_icon, *act_file, *act_compact, *act_voice, *act_find; QAction *act_send, *act_scrollup, *act_scrolldown, *act_close; int pending; @@ -268,11 +270,18 @@ // tool area QVBoxLayout *vb3 = new QVBoxLayout(sp_bottom, 0, 4); + QHBoxLayout *hb3a = new QHBoxLayout(vb3); + d->typeahead = new TypeAheadFindBar(d->log, tr("Find toolbar"), 0); + hb3a->addWidget( d->typeahead ); + QHBoxLayout *hb3 = new QHBoxLayout(vb3); d->act_clear = new IconAction (tr("Clear chat window"), "psi/clearChat", tr("Clear chat window"), 0, this); connect( d->act_clear, SIGNAL( activated() ), SLOT( doClearButton() ) ); + d->act_find = new IconAction(tr("Find"), "psi/search", tr("&Find"), 0, this); + connect(d->act_find, SIGNAL(activated()), d->typeahead, SLOT(open())); + connect(pa->psi()->iconSelectPopup(), SIGNAL(textSelected(QString)), d, SLOT(addEmoticon(QString))); d->act_icon = new IconAction( tr( "Select icon" ), "psi/smile", tr( "Select icon" ), 0, this ); d->act_icon->setMenu( pa->psi()->iconSelectPopup() ); @@ -314,6 +323,7 @@ d->toolbar = new QToolBar(tr("Chat toolbar"), sp_bottom); d->toolbar->setIconSize(QSize(16,16)); d->toolbar->addAction(d->act_clear); + d->toolbar->addAction(d->act_find); d->toolbar->addWidget(new StretchWidget(d->toolbar)); d->toolbar->addAction(d->act_icon); d->toolbar->addAction(d->act_file); @@ -417,6 +427,7 @@ void ChatDlg::setShortcuts() { d->act_clear->setShortcuts(ShortcutManager::instance()->shortcuts("chat.clear")); + d->act_find->setShortcuts(ShortcutManager::instance()->shortcuts("chat.find")); d->act_info->setShortcuts(ShortcutManager::instance()->shortcuts("common.user-info")); d->act_history->setShortcuts(ShortcutManager::instance()->shortcuts("common.history")); //d->act_send->setShortcuts(ShortcutManager::instance()->shortcuts("chat.send")); @@ -829,6 +840,7 @@ setLooks(); setShortcuts(); + d->typeahead->optionsUpdate(); if(isHidden()) { if(option.delChats == dcClose) { diff -rN -u old-psi2/src/eventdlg.cpp new-psi2/src/eventdlg.cpp --- old-psi2/src/eventdlg.cpp 2007-01-25 22:54:10.046875000 +0100 +++ new-psi2/src/eventdlg.cpp 2007-01-25 22:54:46.312500000 +0100 @@ -72,6 +72,7 @@ #include "httpauthmanager.h" #include "psicontactlist.h" #include "accountlabel.h" +#include "typeaheadfind.h" #include "xdata_widget.h" static QString findJid(const QString &s, int x, int *p1, int *p2) @@ -510,7 +511,7 @@ ELineEdit *le_to; QLineEdit *le_from, *le_subj; QLabel *lb_count; - IconToolButton *tb_url, *tb_info, *tb_history, *tb_pgp, *tb_icon; + IconToolButton *tb_url, *tb_info, *tb_history, *tb_pgp, *tb_icon, *tb_find; IconLabel *lb_pgp; bool enc; int transid; @@ -518,6 +519,7 @@ IconButton *pb_close, *pb_quote, *pb_deny, *pb_send, *pb_reply, *pb_chat, *pb_auth, *pb_http_confirm, *pb_http_deny; IconButton *pb_form_submit, *pb_form_cancel; ChatView *mle; + TypeAheadFindBar *typeahead; AttachView *attachView; QTimer *whois; QString lastWhois; @@ -780,6 +782,12 @@ d->lb_count->setAlignment(Qt::AlignRight | Qt::AlignVCenter); d->lb_count->setNum(0); + if(!d->composing) { + d->tb_find = new IconToolButton(this); + d->tb_find->setPsiIcon(IconsetFactory::iconPtr("psi/search")); + d->tb_find->setToolTip(tr("Find")); + connect(d->tb_find, SIGNAL(clicked()), this, SLOT(doFind())); + } if(d->composing) { d->tb_pgp = new IconToolButton(this); @@ -804,6 +812,8 @@ d->tb_history->setToolTip(tr("Message history")); QList toolButtons; + if (!d->composing) + toolButtons << d->tb_find; toolButtons << d->tb_url << d->tb_info << d->tb_history; if (PsiOptions::instance()->getOption("options.pgp.enable").toBool()) toolButtons << d->tb_pgp; @@ -821,6 +831,8 @@ hb3->addWidget(l); hb3->addWidget(d->le_subj); hb3->addWidget(d->lb_count); + if(!d->composing) + hb3->addWidget(d->tb_find); hb3->addWidget(d->tb_icon); hb3->addWidget(d->tb_url); hb3->addWidget(d->tb_info); @@ -836,6 +848,8 @@ } else { d->le_subj->hide(); hb2->addWidget(d->lb_count); + if(!d->composing) + hb3->addWidget(d->tb_find); hb2->addWidget(d->tb_icon); hb2->addWidget(d->tb_url); hb2->addWidget(d->tb_info); @@ -860,6 +874,14 @@ d->mle->setUndoRedoEnabled(false); } + // typeahead find bar + if(!d->composing) { + d->typeahead = new TypeAheadFindBar(d->mle, tr("Find toolbar"), 0); + vb1->addWidget(d->typeahead); + } + else + d->typeahead = 0; + // attachment view d->attachView = new AttachView(this); d->attachView->setFixedHeight(80); @@ -996,6 +1018,8 @@ ShortcutManager::connect("common.user-info", this, SLOT(doInfo())); ShortcutManager::connect("common.history", this, SLOT(doHistory())); //ShortcutManager::connect("message.send", this, SLOT(doSend())); + if (d->typeahead) + ShortcutManager::connect("chat.find", this, SLOT(doFind())); } void EventDlg::setAccount(PsiAccount *pa) @@ -1377,6 +1401,10 @@ setWindowIcon(d->anim->icon()); } #endif + + // typeahead + if (d->typeahead) + d->typeahead->optionsUpdate(); } QSize EventDlg::defaultSize() @@ -1680,6 +1708,11 @@ d->pa->actionInfo(d->jid); } +void EventDlg::doFind() +{ + d->typeahead->open(); +} + void EventDlg::closeAfterReply() { if(d->nextAmount == 0) diff -rN -u old-psi2/src/eventdlg.h new-psi2/src/eventdlg.h --- old-psi2/src/eventdlg.h 2007-01-25 22:54:10.046875000 +0100 +++ new-psi2/src/eventdlg.h 2007-01-25 22:54:46.328125000 +0100 @@ -175,6 +175,7 @@ void doHttpDeny(); void doInfo(); void doHistory(); + void doFind(); void showHideAttachView(); void addUrl(); void doFormSubmit(); diff -rN -u old-psi2/src/groupchatdlg.cpp new-psi2/src/groupchatdlg.cpp --- old-psi2/src/groupchatdlg.cpp 2007-01-25 22:54:10.125000000 +0100 +++ new-psi2/src/groupchatdlg.cpp 2007-01-25 22:54:46.890625000 +0100 @@ -73,6 +73,7 @@ #include "shortcutmanager.h" #include "psicontactlist.h" #include "accountlabel.h" +#include "typeaheadfind.h" #ifdef Q_WS_WIN #include @@ -410,6 +411,7 @@ GCUserView *lv_users; QPushButton *pb_topic; QToolBar *toolbar; + TypeAheadFindBar *typeahead; IconAction *act_find, *act_clear, *act_icon, *act_configure; QAction *act_send, *act_scrollup, *act_scrolldown, *act_close; QLabel* lb_ident; @@ -424,9 +426,6 @@ QStringList hist; int histAt; - QPointer findDlg; - QString lastSearch; - QPointer configDlg; public: @@ -470,27 +469,6 @@ te_log->scrollToBottom(); } -public: - bool internalFind(QString str, bool startFromBeginning = false) - { - if (startFromBeginning) { - QTextCursor cursor = te_log->textCursor(); - cursor.movePosition(QTextCursor::Start, QTextCursor::KeepAnchor); - cursor.clearSelection(); - te_log->setTextCursor(cursor); - } - - bool found = te_log->find(str); - if(!found) { - if (!startFromBeginning) - return internalFind(str, true); - - return false; - } - - return true; - } - private: void removeTrackBar(QTextCursor &cursor) { @@ -779,7 +757,6 @@ d->connecting = false; d->histAt = 0; - d->findDlg = 0; d->configDlg = 0; d->state = Private::Connected; @@ -820,10 +797,6 @@ PsiToolTip::install(d->le_topic); hb_top->addWidget(d->le_topic); - d->act_find = new IconAction(tr("Find"), "psi/search", tr("&Find"), 0, this); - connect(d->act_find, SIGNAL(activated()), SLOT(openFind())); - d->act_find->addTo( sp_top_top ); - d->lb_ident = new AccountLabel(d->pa, sp_top_top, true); d->lb_ident->setSizePolicy(QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum )); hb_top->addWidget(d->lb_ident); @@ -853,10 +826,18 @@ dlg_layout->addWidget( sp_bottom ); QVBoxLayout *vb_bottom = new QVBoxLayout(sp_bottom, 0, 4); + // typeahead find bar + d->typeahead = new TypeAheadFindBar(d->te_log, tr("Find toolbar"), 0); + d->typeahead->displayIconText(true); + vb_bottom->addWidget( d->typeahead ); + // toolbar d->act_clear = new IconAction (tr("Clear chat window"), "psi/clearChat", tr("Clear chat window"), 0, this); connect( d->act_clear, SIGNAL( activated() ), SLOT( doClearButton() ) ); - + + d->act_find = new IconAction(tr("Find"), "psi/search", tr("&Find"), 0, this); + connect(d->act_find, SIGNAL(activated()), d->typeahead, SLOT(open())); + d->act_configure = new IconAction(tr("Configure Room"), "psi/configure-room", tr("&Configure Room"), 0, this); connect(d->act_configure, SIGNAL(activated()), SLOT(configureRoom())); @@ -867,6 +848,7 @@ d->toolbar = new QToolBar( tr("Groupchat toolbar"), 0); d->toolbar->setIconSize(QSize(16,16)); d->toolbar->addAction(d->act_clear); + d->toolbar->addAction(d->act_find); d->toolbar->addAction(d->act_configure); d->toolbar->addWidget(new StretchWidget(d->toolbar)); d->toolbar->addAction(d->act_icon); @@ -1147,17 +1129,6 @@ doClear(); } -void GCMainDlg::openFind() -{ - if(d->findDlg) - bringToFront(d->findDlg); - else { - d->findDlg = new GCFindDlg(d->lastSearch, this); - connect(d->findDlg, SIGNAL(find(const QString &)), SLOT(doFind(const QString &))); - d->findDlg->show(); - } -} - void GCMainDlg::configureRoom() { if(d->configDlg) @@ -1170,15 +1141,6 @@ } } -void GCMainDlg::doFind(const QString &str) -{ - d->lastSearch = str; - if (d->internalFind(str)) - d->findDlg->found(); - else - d->findDlg->error(str); -} - void GCMainDlg::goDisc() { if(d->state != Private::Idle) { @@ -1779,6 +1741,7 @@ setLooks(); setShortcuts(); + d->typeahead->optionsUpdate(); // update status icons d->lv_users->updateAll(); diff -rN -u old-psi2/src/groupchatdlg.h new-psi2/src/groupchatdlg.h --- old-psi2/src/groupchatdlg.h 2007-01-25 22:54:10.125000000 +0100 +++ new-psi2/src/groupchatdlg.h 2007-01-25 22:54:46.984375000 +0100 @@ -150,9 +150,7 @@ void scrollDown(); void mle_returnPressed(); void doTopic(); - void openFind(); void configureRoom(); - void doFind(const QString &); void flashAnimate(); void pa_updatedActivity(); void goDisc(); diff -rN -u old-psi2/src/widgets/typeaheadfind.cpp new-psi2/src/widgets/typeaheadfind.cpp --- old-psi2/src/widgets/typeaheadfind.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new-psi2/src/widgets/typeaheadfind.cpp 2007-01-25 22:54:58.265625000 +0100 @@ -0,0 +1,269 @@ +/* + * typeaheadfind.cpp - Typeahead find toolbar + * Copyright (C) 2006 Maciej Niedzielski + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "typeaheadfind.h" + +#include +#include +#include +#include +#include + +#include "iconaction.h" +#include "stretchwidget.h" +#include "shortcutmanager.h" + +/** + * \class TypeAheadFindBar + * \brief The TypeAheadFindBar class provides a toolbar for typeahead finding. + */ + +class TypeAheadFindBar::Private +{ +public: + // setup search and react to search results + void doFind(bool backward = false) + { + QTextDocument::FindFlags options; + + if (caseSensitive) + options |= QTextDocument::FindCaseSensitively; + + if (backward) { + options |= QTextDocument::FindBackward; + + // move cursor before currect selection + // to prevent finding the same occurence again + QTextCursor cursor = te->textCursor(); + cursor.setPosition(cursor.selectionStart()); + cursor.movePosition(QTextCursor::Left); + te->setTextCursor(cursor); + } + + if (find(text, options)) { + le_find->setStyleSheet(""); + } + else { + le_find->setStyleSheet("QLineEdit { background: #ff6666; color: #ffffff }"); + } + } + + // real search code + + bool find(const QString &str, QTextDocument::FindFlags options, QTextCursor::MoveOperation start = QTextCursor::NoMove) + { + if (start != QTextCursor::NoMove) { + QTextCursor cursor = te->textCursor(); + cursor.movePosition(start); + te->setTextCursor(cursor); + } + + bool found = te->find(text, options); + if (!found) { + if (start == QTextCursor::NoMove) + return find(text, options, options & QTextDocument::FindBackward ? QTextCursor::End : QTextCursor::Start); + + return false; + } + + return true; + } + + QString text; + bool caseSensitive; + + QTextEdit *te; + QAction *act_close; + QLineEdit *le_find; + QAction *act_next; + QAction *act_prev; + QCheckBox *cb_case; +}; + +/** + * \brief Creates new find toolbar, hidden by default. + * \param textedit, QTextEdit that this toolbar will operate on. + * \param title, toolbar's title + * \param parent, toolbar's parent + */ +TypeAheadFindBar::TypeAheadFindBar(QTextEdit *textedit, const QString &title, QWidget *parent) +: QToolBar(title, parent) +{ + d = new Private(); + + setIconSize(QSize(16,16)); + setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + + d->te = textedit; + d->caseSensitive = false; + d->text = ""; + + d->act_close = new IconAction(tr("Close"), "psi/close", "", 0, this); + d->act_close->setToolTip(tr("Close")); + connect(d->act_close, SIGNAL(activated()), SLOT(close())); + addAction(d->act_close); + + addSeparator(); + + addWidget(new QLabel("Search: ", this)); + + d->le_find = new QLineEdit(this); + d->le_find->setMaximumWidth(128); + connect(d->le_find, SIGNAL(textEdited(const QString &)), SLOT(textChanged(const QString &))); + addWidget(d->le_find); + + d->act_next = new IconAction(tr("Find next"), "psi/arrowDown", "", 0, this); + d->act_next->setEnabled(false); + connect(d->act_next, SIGNAL(activated()), SLOT(findNext())); + addAction(d->act_next); + + d->act_prev = new IconAction(tr("Find previous"), "psi/arrowUp", "", 0, this); + d->act_prev->setEnabled(false); + connect(d->act_prev, SIGNAL(activated()), SLOT(findPrevious())); + addAction(d->act_prev); + + d->cb_case = new QCheckBox("&Case sensitive", this); + connect(d->cb_case, SIGNAL(stateChanged(int)), SLOT(caseToggled(int))); + addWidget(d->cb_case); + + addWidget(new StretchWidget(this)); + + optionsUpdate(); + + hide(); +} + +/** + * \brief Destroys the toolbar. + */ +TypeAheadFindBar::~TypeAheadFindBar() +{ + delete d; + d = 0; +} + +/** + * \brief Should be called when application options are changed. + * This slot updates toolbar's shortcuts. + */ +void TypeAheadFindBar::optionsUpdate() +{ + d->act_close->setShortcuts(ShortcutManager::instance()->shortcuts("common.close")); + d->act_next->setShortcuts(ShortcutManager::instance()->shortcuts("chat.find-next")); + d->act_prev->setShortcuts(ShortcutManager::instance()->shortcuts("chat.find-prev")); +} + +/** + * \brief Opens (shows) the toolbar. + */ +void TypeAheadFindBar::open() +{ + show(); + d->le_find->setFocus(); + d->le_find->selectAll(); + emit visibilityChanged(true); +} + +/** + * \brief Closes (hides) the toolbar. + */ +void TypeAheadFindBar::close() +{ + hide(); + emit visibilityChanged(false); +} + +/** + * \brief Switched between visible and hidden state. + */ +void TypeAheadFindBar::toggleVisibility() +{ + if (isVisible()) + hide(); + else + show(); +} + +/** + * \brief Enable icons text if \a yes is true. + */ +void TypeAheadFindBar::displayIconText(bool yes) +{ + if (yes) { + d->act_next->setIconText(tr("Find &next")); + d->act_prev->setIconText(tr("Find &previous")); + } + else { + d->act_next->setIconText(""); + d->act_prev->setIconText(""); + } +} + +/** + * \brief Private slot activated when find text chagnes. + */ +void TypeAheadFindBar::textChanged(const QString &str) +{ + QTextCursor cursor = d->te->textCursor(); + + if (str.isEmpty()) { + d->act_next->setEnabled(false); + d->act_prev->setEnabled(false); + d->le_find->setStyleSheet(""); + cursor.clearSelection(); + d->te->setTextCursor(cursor); + } + else { + d->act_next->setEnabled(true); + d->act_prev->setEnabled(true); + + // don't jump to next word occurence after appending new charater + cursor.setPosition(cursor.selectionStart()); + d->te->setTextCursor(cursor); + + d->text = str; + d->doFind(); + } +} + +/** + * \brief Private slot activated when find-next is requested. + */ +void TypeAheadFindBar::findNext() +{ + d->doFind(); +} + +/** + * \brief Private slot activated when find-prev is requested. + */ +void TypeAheadFindBar::findPrevious() +{ + d->doFind(true); +} + +/** + * \brief Private slot activated when case-sensitive box is toggled. + */ +void TypeAheadFindBar::caseToggled(int state) +{ + d->caseSensitive = (state == QCheckBox::On); +} diff -rN -u old-psi2/src/widgets/typeaheadfind.h new-psi2/src/widgets/typeaheadfind.h --- old-psi2/src/widgets/typeaheadfind.h 1970-01-01 01:00:00.000000000 +0100 +++ new-psi2/src/widgets/typeaheadfind.h 2007-01-25 22:54:58.218750000 +0100 @@ -0,0 +1,57 @@ +/* + * typeaheadfind.h - Typeahead find toolbar + * Copyright (C) 2006 Maciej Niedzielski + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef TYPEAHEADFIND_H +#define TYPEAHEADFIND_H + +#include + +class QTextEdit; +class QString; + +class TypeAheadFindBar : public QToolBar +{ + Q_OBJECT +public: + TypeAheadFindBar(QTextEdit *textedit, const QString &title, QWidget *parent = 0); + ~TypeAheadFindBar(); + +public slots: + void open(); + void close(); + void toggleVisibility(); + void optionsUpdate(); + void displayIconText(bool yes); + +signals: + void visibilityChanged(bool visible); + +private slots: + void textChanged(const QString &); + void findNext(); + void findPrevious(); + void caseToggled(int); + +private: + class Private; + Private *d; +}; + +#endif diff -rN -u old-psi2/src/widgets/widgets.pri new-psi2/src/widgets/widgets.pri --- old-psi2/src/widgets/widgets.pri 2007-01-25 22:54:23.203125000 +0100 +++ new-psi2/src/widgets/widgets.pri 2007-01-25 22:54:59.640625000 +0100 @@ -14,7 +14,8 @@ $$PWD/psirichtext.cpp \ $$PWD/psitooltip.cpp \ $$PWD/psitabwidget.cpp \ - $$PWD/psitabbar.cpp + $$PWD/psitabbar.cpp \ + $$PWD/typeaheadfind.cpp HEADERS += \ $$PWD/stretchwidget.h \ @@ -36,7 +37,8 @@ $$PWD/psirichtext.h \ $$PWD/psitooltip.h \ $$PWD/psitabwidget.h \ - $$PWD/psitabbar.h + $$PWD/psitabbar.h \ + $$PWD/typeaheadfind.h # to remove dependency on iconset and stuff #DEFINES += WIDGET_PLUGIN