/* (c) Copyright 2012 - 2018 Anton Sviridenko https://picapica.im 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, version 3. 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, see . */ #include "chatwindow.h" #include "globals.h" #include "contacts.h" #include "accounts.h" #include #include #include #include #include #include #include #include ChatWindow::ChatWindow(QByteArray peer_id, QString status) : QWidget(0), peer_id_(peer_id), hist(config_dbname, Accounts::GetCurrentAccount().id) { QVBoxLayout *layout; set_peer_name(); { Contacts ct(config_dbname, Accounts::GetCurrentAccount().id); QList L = ct.GetContacts(Contacts::temporary); addcontactquestion = false; for (int i = 0; i < L.size(); i++) { if (L[i].id == peer_id_) { addcontactquestion = true; break; } } } { Accounts ac(config_dbname); my_name_ = ac.GetName(Accounts::GetCurrentAccount().id); if (my_name_.isEmpty()) my_name_ = Accounts::GetCurrentAccount().id.toBase64(); } layout = new QVBoxLayout; lbConnStatus = new QLabel(status); chatw = new QTextEdit(this); sendtextw = new TextSend(this); connect(sendtextw, SIGNAL(send_pressed()), this, SLOT(send_message())); sendtextw->setMinimumHeight(48); sendtextw->setMinimumWidth(240); sendtextw->setAcceptRichText(false); { QFont f = lbConnStatus->font(); f.setBold(true); //f.setItalic(true); f.setStyleHint(QFont::Monospace); lbConnStatus->setFont(f); } chatw->setReadOnly(true); layout->addWidget(lbConnStatus, 0); layout->addWidget(chatw, 3); layout->addWidget(sendtextw, 1, Qt::AlignBottom); if (addcontactquestion) { QHBoxLayout *hl = new QHBoxLayout(); lbAddCtQuestion = new QLabel(tr("Do you want to add \"%1\" to your contact list?").arg(peer_name_)); btAddCtYes = new QPushButton(tr("Yes")); btAddCtNo = new QPushButton(tr("No")); btAddCtBlacklist = new QPushButton(tr("Add to blacklist")); layout->insertWidget(2, lbAddCtQuestion, Qt::AlignLeft); hl->addWidget(btAddCtYes); hl->addWidget(btAddCtNo); hl->addWidget(btAddCtBlacklist); layout->insertLayout(3, hl); connect(btAddCtYes, SIGNAL(clicked()), this, SLOT(addct_yes())); connect(btAddCtNo, SIGNAL(clicked()), this, SLOT(addct_no())); connect(btAddCtBlacklist, SIGNAL(clicked()), this, SLOT(addct_blacklist())); } setLayout(layout); setWindowIcon(picapica_ico_sit); QWidget::setAttribute(Qt::WA_DeleteOnClose); QWidget::setAttribute(Qt::WA_QuitOnClose, false); menu = new QMenuBar(this); hist24h = new QAction(tr("Last 24 &Hours"), this); hist1week = new QAction(tr("Last &Week"), this); histAll = new QAction(tr("&All"), this); histSearch = new QAction(tr("&Search History..."), this); { QMenu *m; m = menu->addMenu(tr("&History")); m = m->addMenu(tr("Show History")); m->addAction(hist24h); m->addAction(hist1week); m->addAction(histAll); m->addAction(histSearch); } layout->insertSpacing(0, menu->size().height()); connect(hist24h, SIGNAL(triggered()), this, SLOT(show_history24h())); connect(hist1week, SIGNAL(triggered()), this, SLOT(show_history1w())); connect(histAll, SIGNAL(triggered()), this, SLOT(show_historyAll())); connect(histSearch, SIGNAL(triggered()), this, SLOT(show_historySearch())); } void ChatWindow::update_status(QString status) { lbConnStatus->setText(status); } void ChatWindow::put_message(QString msg, QByteArray id, bool is_me) { QString color, name; QTextCharFormat fmt; int pos; if (is_me) { color = "#0000ff"; name = my_name_; } else { color = "#ff0000"; if (id == peer_id_) name = peer_name_; else name = id.toBase64(); } pos = draw_message(msg, name, QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"), color, false); if (is_me) undelivered_msgs.append(pos); } int ChatWindow::draw_message(QString msg, QString nickname, QString datetime, QString color, bool is_delivered) { QTextCharFormat fmt; QString delivered_mark; int ret; if (is_delivered) delivered_mark = "+"; else delivered_mark = " "; QTextCursor c(chatw->document()); c.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); ret = c.position(); chatw->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); fmt = chatw->currentCharFormat(); chatw->insertHtml( QString("%2(%3) %4 : "). arg(color). arg(delivered_mark). arg(datetime). arg(nickname) ); chatw->setCurrentCharFormat(fmt); chatw->insertPlainText(msg + '\n'); chatw->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); return ret; } void ChatWindow::print_history(QList H) { chatw->clear(); while(!H.isEmpty()) { History::HistoryRecord r = H.takeFirst(); QString color, name; QDateTime dt; if (r.is_me) { color = "#0000ff"; name = my_name_; } else { color = "#ff0000"; if (r.peer_id == peer_id_) name = peer_name_; else name = r.peer_id.toBase64(); } dt.setTime_t(r.timestamp); //put_message(r.message, r.peer_id, r.is_me); draw_message(r.message, name, dt.toString("yyyy-MM-dd hh:mm:ss"), color, r.is_delivered); } } void ChatWindow::msg_from_peer(QString msg) { if (isMinimized()) showNormal(); put_message(msg, peer_id_, false); hist.Add(peer_id_, msg, false); } void ChatWindow::msg_delivered() { if (undelivered_msgs.isEmpty()) { // undelivered_msgs can be empty if new chatwindow instance was created // and undelivered message from previous chat session is delivered // after that. QByteArray my_id = Accounts::GetCurrentAccount().id; QMap > undl = hist.GetUndeliveredMessages(); if (!undl[my_id].isEmpty()) put_message(undl[my_id].first(), my_id, true); } if (!undelivered_msgs.isEmpty()) { QTextCursor c(chatw->document()); c.setPosition(undelivered_msgs.first()); c.deleteChar(); c.insertText("+"); undelivered_msgs.removeFirst(); } hist.SetDelivered(peer_id_); } void ChatWindow::msg_informational(QString text) { QString color; QTextCharFormat fmt; color = "#303030"; fmt = chatw->currentCharFormat(); chatw->insertHtml( QString("(%2)"). arg(color). arg(text) ); chatw->insertPlainText("\n"); chatw->setCurrentCharFormat(fmt); chatw->moveCursor(QTextCursor::End, QTextCursor::KeepAnchor); } bool ChatWindow::isEmptyMessage(const QString &msg) const { int size = msg.size(); for (int i = 0; i < size; ++i) { if (!msg.at(i).isSpace()) { return false; } } return true; } void ChatWindow::send_message() { QString message = sendtextw->toPlainText(); if (!isEmptyMessage(message)) { put_message(message, Accounts::GetCurrentAccount().id, true); hist.Add(peer_id_, message, true); if (!hist.isOK()) { QMessageBox mbx; mbx.setText(hist.GetLastError()); mbx.exec(); } emit msg_input(message, this); sendtextw->clear(); } } void ChatWindow::closeEvent(QCloseEvent *e) { emit chatwindow_close(this); e->accept(); } TextSend::TextSend(QWidget *parent) : QTextEdit(parent) { } void TextSend::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Return && e->modifiers() == Qt::NoModifier ) { emit send_pressed(); return; } QTextEdit::keyPressEvent(e); } void ChatWindow::show_history24h() { print_history(hist.GetMessages(peer_id_, QDateTime::currentDateTime().addDays(-1).toTime_t(), QDateTime::currentDateTime().toTime_t())); } void ChatWindow::show_history1w() { print_history(hist.GetMessages(peer_id_, QDateTime::currentDateTime().addDays(-7).toTime_t(), QDateTime::currentDateTime().toTime_t())); } void ChatWindow::show_historyAll() { print_history(hist.GetMessages(peer_id_, 0, QDateTime::currentDateTime().toTime_t())); } void ChatWindow::show_historySearch() { bool ok; QString keyword = QInputDialog::getText(this, tr("Search in message history"), tr("Find:"), QLineEdit::Normal, QString(), &ok); if (ok) print_history(hist.GetMessages(peer_id_, keyword)); } void ChatWindow::addct_yes() { Contacts ct(config_dbname, Accounts::GetCurrentAccount().id); ct.Add(peer_id_, Contacts::regular); addct_removequestion(); emit contacts_update(); } void ChatWindow::addct_no() { addct_removequestion(); } void ChatWindow::addct_blacklist() { Contacts ct(config_dbname, Accounts::GetCurrentAccount().id); ct.Add(peer_id_, Contacts::blacklisted); addct_removequestion(); } void ChatWindow::addct_removequestion() { if (addcontactquestion) { delete btAddCtYes; delete btAddCtNo; delete btAddCtBlacklist; delete lbAddCtQuestion; addcontactquestion = false; } } void ChatWindow::set_peer_name() { QString title; Contacts ct(config_dbname, Accounts::GetCurrentAccount().id); peer_name_ = ct.GetContactName(peer_id_); title = peer_name_; if (peer_name_.isEmpty()) peer_name_ = peer_id_.toBase64(); title = QObject::tr("Chat with ") + title + " - " + peer_id_.toBase64(); setWindowTitle(title); }