#include "mainwidget.h" #include "ui_mainwidget.h" #include MainWidget::MainWidget(QString username,QWidget *parent) : QWidget(parent), ui(new Ui::MainWidget) { ui->setupUi(this); this->setFixedSize(this->width(), this->height()); this->setWindowIcon(QIcon(":/icon.png")); this->setWindowTitle(QString("TCP聊天室:%1").arg(username)); this->setAttribute(Qt::WA_StyledBackground); ui->name_list->setEditTriggers(QAbstractItemView::NoEditTriggers); //不允许编辑 //ui->name_list->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); //ui->name_list->verticalScrollBar()->setStyleSheet("QScrollBar{width:16px;}"); /****************文本显示栏初始设置********************/ ui->textEdit->setReadOnly(true); ui->textEdit->setFocusPolicy(Qt::NoFocus); //防止QTextBrowser中的内容被重定向 ui->textEdit->setOpenLinks(false); ui->textEdit->setOpenExternalLinks(false); connect(ui->textEdit, &QTextBrowser::anchorClicked, this, [=](const QUrl &link) { auto path = link.path(); path.remove(0, 1); qDebug() << path; QFileInfo info(path); if(info.isDir()) QDesktopServices::openUrl(link); else if(info.isFile()) QDesktopServices::openUrl(QUrl::fromLocalFile(path)); }); ui->send_btn->setFocus(); ui->send_btn->setDefault(true); ui->send_text->setMouseTracking(true); ui->send_text->setToolTip(QStringLiteral("发送文件")); ui->stop->setMouseTracking(true); ui->stop->setToolTip(QStringLiteral("注销用户")); ui->exit_btn->setMouseTracking(true); ui->exit_btn->setToolTip(QStringLiteral("退出登录")); ui->save_btn->setMouseTracking(true); ui->save_btn->setToolTip(QStringLiteral("保存聊天记录")); CreateSystemTray(); effect = new QSoundEffect(this); effect->setSource(QUrl("qrc:/remind.wav")); effect->setLoopCount(1); effect->setVolume(0.95f); ui->msg_edit->installEventFilter(this);//设置完后自动调用其eventFilter函数 this->username = username; } MainWidget::~MainWidget() { delete ui; } void MainWidget::on_send_text_clicked() { zoom_down(ui->send_text); zoom_up(ui->send_text); QString homePath = QDir::homePath(); QString filePath = QFileDialog::getOpenFileName(this, tr("Open a file"), homePath, tr("All files (*.*)"), NULL, QFileDialog::DontResolveSymlinks); QString filename = filePath.section("/", -1); if (filename.isEmpty()) return; QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "发送文件", tr("Do you want to send \"%1\"?").arg(filename)); if (reply == QMessageBox::No) return; else { QString text = ui->msg_edit->text(); if(text.isEmpty()) //群发 { QString currentTime = QTime::currentTime().toString("H:mm A"); QString html = "" + filename + ""; qDebug() << html; ui->textEdit->append("

" + username + " [" + currentTime + "] send a file \"" + html + "\"

"); this->sendFile(filePath,filename); } else //私发文件 { ui->msg_edit->clear(); int n = text.indexOf(' '); QString name = text.mid(1,n-1); if(username == name) { QMessageBox::critical(this,"错误","不能自己给自己发送文件!"); return; } int index = 0; for (int i = 0; i < ui->name_list->count(); i++) { if(name != ui->name_list->item(index)->text()) index++; } if(index >= ui->name_list->count()) { QMessageBox::critical(this,"错误","未找到指定用户!"); return; } else { QString currentTime = QTime::currentTime().toString("H:mm A"); QString html = "" + filename + ""; qDebug() << html; ui->textEdit->append("

" + username + " [" + currentTime + "] send " + name + " a private file \"" + html + "\"

"); this->sendFile(filePath,filename,name); } } } } void MainWidget::on_save_btn_clicked() { zoom_down(ui->save_btn); zoom_up(ui->save_btn); QFile file("./ChatRecord/memory.txt"); if (file.exists()) //文件存在 { QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "提示", tr("是否覆盖之前的聊天记录?")); if (reply == QMessageBox::No) { if (file.open(QIODevice::WriteOnly | QIODevice::Append)) { QTextStream stream(&file); //转换为字符串 QString str = ui->textEdit->toPlainText(); QString date = QDate::currentDate().toString("yyyy-MM-dd "); QString currentTime = QTime::currentTime().toString("H:mm A\n"); str = "\n\n" + date + currentTime + str; //加入时间戳并写入 stream << str; //关闭文件 file.close(); QMessageBox::information(this,"保存聊天记录","保存成功!"); } } else { if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); //转换为字符串 QString str = ui->textEdit->toPlainText(); QString date = QDate::currentDate().toString("yyyy-MM-dd "); QString currentTime = QTime::currentTime().toString("H:mm A\n"); str = date + currentTime + str + "\n"; stream << str; //关闭文件 file.close(); QMessageBox::information(this,"保存聊天记录","保存成功!"); } } } else { QMessageBox::warning(this, "提示", tr("聊天记录文件不存在,已为您自动创建文件!")); file.open(QIODevice::WriteOnly | QIODevice::Append); } } void MainWidget::on_send_btn_clicked() { zoom_down(ui->send_btn); zoom_up(ui->send_btn); QString text = ui->msg_edit->text(); if(text.isEmpty()) { QMessageBox::warning(this, "发送失败", "输入不能为空!"); return; } ui->msg_edit->clear(); if(text[0] == '@') { int n = text.indexOf(' '); QString to_user = text.mid(1,n-1); QString insert = "tell you quietly:"; QString data_text = insert + text.mid(n,-1); QString text_self = QString("私发给%1:%2").arg(to_user, text.mid(n)); qDebug() << text_self; if(username == to_user) { QMessageBox::critical(this,"错误","不能自己给自己发送文件!"); return; } int index = 0; for (int i = 0; i < ui->name_list->count(); i++) { if(to_user != ui->name_list->item(index)->text()) index++; } if(index >= ui->name_list->count()) { QMessageBox::critical(this,"错误","未找到指定用户!"); return; } else { QString currentTime = QTime::currentTime().toString("H:m A"); ui->textEdit->append("

" + username + " [" + currentTime + "] " + text_self + "

"); emit send_to_user(username,to_user,data_text); } } else { QString currentTime = QTime::currentTime().toString("H:m A"); ui->textEdit->append("

" + username + " [" + currentTime + "] : " + text + "

"); emit send_text(username,text); } } void MainWidget::on_name_list_itemDoubleClicked(QListWidgetItem *item) { QString client_name = ui->name_list->currentItem()->text(); QString a = "@"; a = a + client_name + " "; ui->msg_edit->clear(); ui->msg_edit->setText(a); } void MainWidget::on_exit_btn_clicked() { zoom_down(ui->exit_btn); zoom_up(ui->exit_btn); close(); } void MainWidget::on_stop_clicked() { zoom_down(ui->stop); zoom_up(ui->stop); QMessageBox::StandardButton response; response = QMessageBox::question(this, "注销", tr("是否退出软件并注销账户?")); if(response == QMessageBox::Yes) { qDebug() << "点击注销账户按钮"; //emit exit_client(); emit account_cancellation(username); this->close(); } else { return; } } void MainWidget::update_text(QString sendname,QString data) { QString currentTime = QTime::currentTime().toString("H:m A"); ui->textEdit->append("

" + sendname + " [" + currentTime + "] : " + data + "

"); qDebug() << sendname + " [" + currentTime + "] : " + data; } void MainWidget::update_file(QString sendname,QString filename,QString file_data) { readFile(filename,QByteArray::fromHex(file_data.toUtf8())); QString currentTime = QTime::currentTime().toString("H:m A"); QString html = "" + filename + ""; QString msg = "

" + username + " [" + currentTime + "] : " + QString("收到了一个来自%1的群发文件:").arg(sendname) + html + "

"; ui->textEdit->append(msg); qDebug() << msg; } void MainWidget::update_file_private(QString sendname,QString filename,QString file_data) { readFile(filename,QByteArray::fromHex(file_data.toUtf8())); QString currentTime = QTime::currentTime().toString("H:m A"); QString html = "" + filename + ""; QString msg = "

" + username + " [" + currentTime + "] : " + QString("收到了一个来自%1的私发文件:").arg(sendname) + html + "

"; ui->textEdit->append(msg); qDebug() << msg; } /* void MainWidget::update_file(QString sendname,QString filename,QString file_data) { QMessageBox::StandardButton response; QString content = QString("你收到了一个来自%1的群发文件%2,是否接收?").arg(sendname).arg(filename); response = QMessageBox::question(this,"提示",content); if(response == QMessageBox::Yes) { readFile(filename,file_data.toUtf8()); QString currentTime = QTime::currentTime().toString("H:m A"); ui->textEdit->append(QString(username + " [" + currentTime + "] : " + "收到了一个来自%1的群发文件%2").arg(sendname).arg(filename)); } else { QMessageBox::information(this,"接收文件","未接收该文件!"); } } void MainWidget::update_file_private(QString sendname,QString filename,QString file_data) { QMessageBox::StandardButton response; QString content = QString("你收到了%1私发给你的文件%2,是否接收?").arg(sendname).arg(filename); response = QMessageBox::question(this,"提示",content); if(response == QMessageBox::Yes) { readFile(filename,file_data.toUtf8()); QString currentTime = QTime::currentTime().toString("H:m A"); ui->textEdit->append(QString(username + " [" + currentTime + "] :" + "收到了一个来自%1的私发文件%2").arg(sendname).arg(filename)); } else { QMessageBox::information(this,"消息","未接收该文件!"); } } */ void MainWidget::update_users(int count,QListonline_users) { ui->name_list->clear(); QList::iterator it = online_users.begin(); for(; it!=online_users.end(); ++it) { ui->name_list->addItem(*it); } for(int i=0;iname_list->count();i++) { ui->name_list->item(i)->setIcon(QIcon(":/user_label.png")); } } void MainWidget::disconnect_form_server() { QMessageBox::critical(this,"连接超时","请检查您的网络连接!"); qApp->quit(); } void MainWidget::slot_new_message() { emit new_message(); } void MainWidget::message_reminder() { QApplication::alert(this);// 任务栏通知 ui->textEdit->append("    " "       " "—————————以下是新消息—————————\n"); disconnect(this,&MainWidget::new_message,this,&MainWidget::message_reminder); if (TimerFlash == NULL) { flashCount = 0; TimerFlash = new QTimer(this); connect(TimerFlash, &QTimer::timeout, this, &MainWidget::onFlashTimerOut); TimerFlash->start(500); } } void MainWidget::onFlashTimerOut() { flashCount++; if (flashCount % 2 == 1) { SystemTray->setIcon(QIcon(":/empty.png")); } else { SystemTray->setIcon(QIcon(":/icon.png")); } } void MainWidget::sendFile(QString filePath,QString filename,QString name) { QFile file(filePath); //打开文件,定义错误提醒 if(!file.open(QIODevice::ReadOnly)){ QMessageBox::warning(this,"错误","无法打开文件!"); return; } //将数据读取到QByteArray QByteArray dataOfFile = file.readAll(); //关闭文件 file.close(); if(name.isEmpty()) //群发文件 { emit send_file_to_all(username,filename,dataOfFile); } else //私发文件 { emit send_file_private(username,filename,dataOfFile,name); } QScopedPointer progressDlg(new QProgressDialog(this)); progressDlg->setWindowModality(Qt::WindowModal); progressDlg->setMinimumDuration(0); progressDlg->setAttribute(Qt::WA_DeleteOnClose, true); progressDlg->setWindowTitle(tr("上传文件")); progressDlg->setLabelText(tr("正在上传......")); progressDlg->setCancelButtonText(tr("取消")); progressDlg->setRange(0, 12000); for (int i = 1; i < 12000; i++) { progressDlg->setValue(i); if (progressDlg->wasCanceled()) { break; } } progressDlg->close(); QMessageBox::information(this,"发送文件","发送成功!"); } void MainWidget::readFile(QString filename,QByteArray data) { QString filepath = "./Document"; QDir dir(filepath); if(dir.exists()) { QFile outFile(filepath + "/" +filename); if(!outFile.open(QIODevice::WriteOnly)){ QMessageBox::warning(this,"错误","接收文件出错!"); return; } outFile.write(data); outFile.close(); } else { dir.mkdir(filepath); QFile outFile(filepath + "/" +filename); if(!outFile.open(QIODevice::WriteOnly)){ QMessageBox::warning(this,"错误","接收文件出错!"); return; } outFile.write(data); outFile.close(); } } void MainWidget::CreateSystemTray() { //创建菜单对象和托盘图标对象 TrayMennu = new QMenu(this); SystemTray = new QSystemTrayIcon(this); //创建菜单项 ActionShow = new QAction(tr("Show"), this); ActionQuit = new QAction(tr("Exit"), this); connect(ActionShow,&QAction::triggered,this,[=](){ if(this->isMinimized()) { this->showNormal(); } this->show(); //SystemTray->hide(); }); connect(ActionQuit,&QAction::triggered,this,[=](){ qApp->quit(); }); connect(SystemTray,&QSystemTrayIcon::activated,this,[=](){ if(this->isMinimized()) { this->showNormal(); } this->show(); //SystemTray->hide(); }); //添加菜单项 TrayMennu->addAction(ActionShow); TrayMennu->addSeparator(); TrayMennu->addAction(ActionQuit); //为系统托盘设置菜单为m_pTrayMennu SystemTray->setContextMenu(TrayMennu); SystemTray->setIcon(QIcon(":/icon.png")); SystemTray->show(); } void MainWidget::zoom_down(QPushButton* btn) { QPointer animalton(new QPropertyAnimation(btn,"geometry")); animalton->setDuration(150); animalton->setStartValue(QRect(btn->x(),btn->y(),btn->width(),btn->height())); animalton->setEndValue(QRect(btn->x(),btn->y()+5,btn->width(),btn->height())); animalton->setEasingCurve(QEasingCurve::OutBounce); animalton->start(); } void MainWidget::zoom_up(QPushButton* btn) { QPointer animalton(new QPropertyAnimation(btn,"geometry")); animalton->setDuration(150); animalton->setStartValue(QRect(btn->x(),btn->y()+5,btn->width(),btn->height())); animalton->setEndValue(QRect(btn->x(),btn->y(),btn->width(),btn->height())); animalton->setEasingCurve(QEasingCurve::OutBounce); animalton->start(); } void MainWidget::changeEvent(QEvent *event) { if(event->type()!=QEvent::WindowStateChange) return; if(this->windowState()==Qt::WindowMinimized) { connect(this,&MainWidget::new_message,this,&MainWidget::message_reminder); connect(this,&MainWidget::new_message,effect, &QSoundEffect::play); } } bool MainWidget::eventFilter(QObject *target, QEvent *event) { if(target == ui->msg_edit) //可替换 { if(event->type() == QEvent::KeyPress)//回车键 { QKeyEvent *k = static_cast(event); if(k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter) { on_send_btn_clicked(); //替换为需要响应的函数事件,以这里的按钮为例 return true; } } } return QWidget::eventFilter(target,event); } void MainWidget::showEvent(QShowEvent *event) { if(TimerFlash != NULL) { qDebug() << "有信息到来显示窗体"; disconnect(this,&MainWidget::new_message,effect, &QSoundEffect::play); SystemTray->setIcon(QIcon(":/icon.png")); delete TimerFlash; TimerFlash = NULL; } } void MainWidget::closeEvent(QCloseEvent *event) { std::function callback; callback = [=](int r)->void{ switch (r) { case QMessageBox::Ok: { event->accept(); qApp->quit(); break; } default: { event->ignore(); this->hide(); connect(this,&MainWidget::new_message,this,&MainWidget::message_reminder); connect(this,&MainWidget::new_message,effect, &QSoundEffect::play); break; } } }; QMessageBox box(QMessageBox::Question,QString("退出"), QString("确定退出软件?否则将最小化窗口"),QMessageBox::Ok|QMessageBox::Cancel); box.button(QMessageBox::Ok)->setText("是"); box.button(QMessageBox::Cancel)->setText("否"); callback(box.exec()); event->ignore(); }