/**************************************************************** * RetroShare is distributed under the following license: * * Copyright (C) 2006, crypton * * 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 program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ****************************************************************/ #include #include "rshare.h" #include "ChatDialog.h" #include "rsiface/rsiface.h" #include "rsiface/rspeers.h" #include "rsiface/rsmsgs.h" #include "rsiface/rsnotify.h" #include "chat/PopupChatDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Constructor */ ChatDialog::ChatDialog(QWidget *parent) : MainPage (parent) { /* Invoke the Qt Designer generated object setup routine */ ui.setupUi(this); loadEmoticonsgroupchat(); setWindowIcon(QIcon(QString(":/images/rstray3.png"))); connect(ui.lineEdit, SIGNAL(textChanged ( ) ), this, SLOT(checkChat( ) )); connect(ui.Sendbtn, SIGNAL(clicked()), this, SLOT(sendMsg())); connect(ui.emoticonBtn, SIGNAL(clicked()), this, SLOT(smileyWidgetgroupchat())); connect( ui.msgSendList, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( msgSendListCostumPopupMenu( QPoint ) ) ); connect( ui.msgText, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayInfoChatMenu(const QPoint&))); connect(ui.textboldChatButton, SIGNAL(clicked()), this, SLOT(setFont())); connect(ui.textunderlineChatButton, SIGNAL(clicked()), this, SLOT(setFont())); connect(ui.textitalicChatButton, SIGNAL(clicked()), this, SLOT(setFont())); connect(ui.fontsButton, SIGNAL(clicked()), this, SLOT(getFont())); connect(ui.colorChatButton, SIGNAL(clicked()), this, SLOT(setColor())); ui.fontsButton->setIcon(QIcon(QString(":/images/fonts.png"))); // connect(ui.msgSendList, SIGNAL(itemChanged( QTreeWidgetItem *, int ) ), // this, SLOT(toggleSendItem( QTreeWidgetItem *, int ) )); /* hide the Tree +/- */ ui.msgSendList -> setRootIsDecorated( false ); /* to hide the header */ ui.msgSendList->header()->hide(); _currentColor = Qt::black; QPixmap pxm(24,24); pxm.fill(_currentColor); ui.colorChatButton->setIcon(pxm); //QFont font = QFont("Comic Sans MS", 10); mCurrentFont = QFont("Comic Sans MS", 12); ui.lineEdit->setFont(mCurrentFont); setChatInfo(tr("Welcome to RetroShare's group chat."), QString::fromUtf8("blue")); QMenu * grpchatmenu = new QMenu(); grpchatmenu->addAction(ui.actionClearChat); ui.menuButton->setMenu(grpchatmenu); _underline = false; QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(insertChat())); timer->start(500); /* half a second */ /* Hide platform specific features */ #ifdef Q_WS_WIN #endif } void ChatDialog::msgSendListCostumPopupMenu( QPoint point ) { QMenu contextMnu( this ); QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); privchatAct = new QAction(QIcon(), tr( "Chat" ), this ); connect( privchatAct , SIGNAL( triggered() ), this, SLOT( privchat() ) ); contextMnu.clear(); contextMnu.addAction( privchatAct); contextMnu.exec( mevent->globalPos() ); } void ChatDialog::insertChat() { if (!rsMsgs->chatAvailable()) { return; } std::list newchat; if (!rsMsgs->getNewChat(newchat)) { return; } QTextEdit *msgWidget = ui.msgText; std::list::iterator it; /** A RshareSettings object used for saving/loading settings */ RshareSettings settings; uint chatflags = settings.getChatFlags(); /* add in lines at the bottom */ for(it = newchat.begin(); it != newchat.end(); it++) { std::string msg(it->msg.begin(), it->msg.end()); std::cerr << "ChatDialog::insertChat(): " << msg << std::endl; /* are they private? */ if (it->chatflags & RS_CHAT_PRIVATE) { std::cerr << "ChatDialog::insert(Private)Chat(): "; std::cerr << "Flags(" << chatflags << ") " << msg << std::endl; PopupChatDialog *pcd = getPrivateChat(it->rsid, it->name, chatflags); pcd->addChatMsg(&(*it)); continue; } std::ostringstream out; QString currenttxt = msgWidget->toHtml(); QString extraTxt; QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss"); QString name = QString::fromStdString(it->name); QString line = "" + timestamp + "" + "" + " " + name + ""; extraTxt += line; extraTxt += QString::fromStdWString(it->msg); /* add it everytime */ currenttxt += extraTxt; QHashIterator i(smileys); while(i.hasNext()) { i.next(); currenttxt.replace(i.key(), ""); } msgWidget->setHtml(currenttxt); QScrollBar *qsb = msgWidget->verticalScrollBar(); qsb -> setValue(qsb->maximum()); } } void ChatDialog::checkChat() { /* if at the end of the text -> we can send it! */ QTextEdit *chatWidget = ui.lineEdit; std::string txt = chatWidget->toPlainText().toStdString(); if ('\n' == txt[txt.length()-1]) { //std::cerr << "Found found at end of :" << txt << ": should send!"; //std::cerr << std::endl; if (txt.length()-1 == txt.find('\n')) /* only if on first line! */ { /* should remove last char ... */ sendMsg(); } } else { //std::cerr << "No found in :" << txt << ":"; //std::cerr << std::endl; } } void ChatDialog::sendMsg() { QTextEdit *lineWidget = ui.lineEdit; ChatInfo ci; //ci.msg = lineWidget->Text().toStdWString(); ci.msg = lineWidget->toHtml().toStdWString(); ci.chatflags = RS_CHAT_PUBLIC; std::string msg(ci.msg.begin(), ci.msg.end()); //std::cerr << "ChatDialog::sendMsg(): " << msg << std::endl; rsMsgs -> ChatSend(ci); ui.lineEdit->clear(); setFont(); /* redraw send list */ insertSendList(); } void ChatDialog::insertSendList() { std::list peers; std::list::iterator it; if (!rsPeers) { /* not ready yet! */ return; } rsPeers->getOnlineList(peers); /* get a link to the table */ QTreeWidget *sendWidget = ui.msgSendList; QList items; for(it = peers.begin(); it != peers.end(); it++) { RsPeerDetails details; if (!rsPeers->getPeerDetails(*it, details)) { continue; /* BAD */ } /* make a widget per friend */ QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); /* add all the labels */ /* (0) Person */ item -> setText(0, QString::fromStdString(details.name)); item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); //item -> setFlags(Qt::ItemIsUserCheckable); item -> setCheckState(0, Qt::Checked); if (rsicontrol->IsInChat(*it)) { item -> setCheckState(0, Qt::Checked); } else { item -> setCheckState(0, Qt::Unchecked); } /* disable for the moment */ item -> setFlags(Qt::ItemIsUserCheckable); item -> setCheckState(0, Qt::Checked); /* add to the list */ items.append(item); } /* remove old items */ sendWidget->clear(); sendWidget->setColumnCount(1); /* add the items in! */ sendWidget->insertTopLevelItems(0, items); sendWidget->update(); /* update display */ } /* to toggle the state */ void ChatDialog::toggleSendItem( QTreeWidgetItem *item, int col ) { //std::cerr << "ToggleSendItem()" << std::endl; /* extract id */ std::string id = (item -> text(4)).toStdString(); /* get state */ bool inChat = (Qt::Checked == item -> checkState(0)); /* alway column 0 */ /* call control fns */ rsicontrol -> SetInChat(id, inChat); return; } void ChatDialog::privchat() { } PopupChatDialog *ChatDialog::getPrivateChat(std::string id, std::string name, uint chatflags) { /* see if it exists already */ PopupChatDialog *popupchatdialog = NULL; bool show = false; if (chatflags & RS_CHAT_REOPEN) { show = true; std::cerr << "reopen flag so: enable SHOW popupchatdialog()"; std::cerr << std::endl; } std::map::iterator it; if (chatDialogs.end() != (it = chatDialogs.find(id))) { /* exists already */ popupchatdialog = it->second; } else { popupchatdialog = new PopupChatDialog(id, name); chatDialogs[id] = popupchatdialog; if (chatflags & RS_CHAT_OPEN_NEW) { std::cerr << "new chat so: enable SHOW popupchatdialog()"; std::cerr << std::endl; show = true; } } if (show) { std::cerr << "SHOWING popupchatdialog()"; std::cerr << std::endl; popupchatdialog->show(); } /* now only do these if the window is visible */ if (popupchatdialog->isVisible()) { if (chatflags & RS_CHAT_FOCUS) { std::cerr << "focus chat flag so: GETFOCUS popupchatdialog()"; std::cerr << std::endl; popupchatdialog->getfocus(); } else { std::cerr << "no focus chat flag so: FLASH popupchatdialog()"; std::cerr << std::endl; popupchatdialog->flash(); } } else { std::cerr << "not visible ... so leave popupchatdialog()"; std::cerr << std::endl; } return popupchatdialog; } void ChatDialog::clearOldChats() { /* nothing yet */ } void ChatDialog::setColor() { bool ok; QRgb color = QColorDialog::getRgba(ui.lineEdit->textColor().rgba(), &ok, this); if (ok) { _currentColor = QColor(color); QPixmap pxm(24,24); pxm.fill(_currentColor); ui.colorChatButton->setIcon(pxm); } setFont(); } void ChatDialog::getFont() { bool ok; mCurrentFont = QFontDialog::getFont(&ok, mCurrentFont, this); setFont(); } void ChatDialog::setFont() { mCurrentFont.setBold(ui.textboldChatButton->isChecked()); mCurrentFont.setUnderline(ui.textunderlineChatButton->isChecked()); mCurrentFont.setItalic(ui.textitalicChatButton->isChecked()); ui.lineEdit->setFont(mCurrentFont); ui.lineEdit->setTextColor(_currentColor); ui.lineEdit->setFocus(); } void ChatDialog::underline() { _underline = !_underline; ui.lineEdit->setFontUnderline(_underline); } // Update Chat Info information void ChatDialog::setChatInfo(QString info, QColor color) { static unsigned int nbLines = 0; ++nbLines; // Check log size, clear it if too big if(nbLines > 200) { ui.msgText->clear(); nbLines = 1; } ui.msgText->append(QString::fromUtf8("")+ QTime::currentTime().toString(QString::fromUtf8("hh:mm:ss")) + QString::fromUtf8(" - ") + info + QString::fromUtf8("")); } void ChatDialog::on_actionClearChat_triggered() { ui.msgText->clear(); } void ChatDialog::displayInfoChatMenu(const QPoint& pos) { // Log Menu QMenu myChatMenu(this); myChatMenu.addAction(ui.actionClearChat); // XXX: Why mapToGlobal() is not enough? myChatMenu.exec(mapToGlobal(pos)+QPoint(0,80)); } void ChatDialog::loadEmoticonsgroupchat() { QDir smdir(QApplication::applicationDirPath() + "/emoticons/kopete"); QFileInfoList sminfo = smdir.entryInfoList(QStringList() << "*.gif" << "*.png", QDir::Files, QDir::Name); foreach(QFileInfo info, sminfo) { QString smcode = info.fileName().replace(".gif", ""); QString smstring; for(int i = 0; i < 9; i+=3) { smstring += QString((char)smcode.mid(i,3).toInt()); } //qDebug(smstring.toAscii()); smileys.insert(smstring, info.absoluteFilePath()); } } void ChatDialog::smileyWidgetgroupchat() { qDebug("MainWindow::smileyWidget()"); QWidget *smWidget = new QWidget; smWidget->setWindowTitle("Emoticons"); smWidget->setWindowIcon(QIcon(QString(":/images/rstray3.png"))); smWidget->setFixedSize(256,256); int x = 0, y = 0; QHashIterator i(smileys); while(i.hasNext()) { i.next(); QPushButton *smButton = new QPushButton("", smWidget); smButton->setGeometry(x*24, y*24, 24,24); smButton->setIconSize(QSize(24,24)); smButton->setIcon(QPixmap(i.value())); smButton->setToolTip(i.key()); //smButton->setFixedSize(24,24); ++x; if(x > 4) { x = 0; y++; } connect(smButton, SIGNAL(clicked()), this, SLOT(addSmileys())); } smWidget->show(); } void ChatDialog::addSmileys() { ui.lineEdit->setText(ui.lineEdit->toHtml() + qobject_cast(sender())->toolTip()); }