实例介绍
【实例简介】
【实例截图】
【核心代码】
#include <QtDebug> #include <QCoreApplication> #include <QDesktopServices> #include <QUrl> #include <QTranslator> #include <QMessageBox> #include <QFileDialog> #include "QsLog.h" #include "mainwindow.h" #include "ui_mainwindow.h" #include "eutils.h" MainWindow *mainWin; MainWindow::MainWindow(QWidget *parent, ModbusAdapter *adapter, ModbusCommSettings *settings) : QMainWindow(parent), m_modbus(adapter), m_modbusCommSettings(settings), ui(new Ui::MainWindow) { //setup UI ui->setupUi(this); ui->sbNoOfRegs->setEnabled(true); ui->actionRead_Write->setEnabled(false); ui->actionScan->setEnabled(false); ui->sbStartAddress->setMinimum(m_modbusCommSettings->baseAddr().toInt()); ui->cmbBase->setCurrentIndex(m_modbusCommSettings->base()); ui->cmbFunctionCode->setCurrentIndex(m_modbusCommSettings->functionCode()); ui->cmbModbusMode->setCurrentIndex(m_modbusCommSettings->modbusMode()); ui->sbSlaveID->setValue(m_modbusCommSettings->slaveID()); ui->spInterval->setValue(m_modbusCommSettings->scanRate()); ui->sbStartAddress->setValue(m_modbusCommSettings->startAddr()); ui->sbNoOfRegs->setValue(m_modbusCommSettings->noOfRegs()); //UI - dialogs m_dlgAbout = new About(); connect(ui->actionAbout,SIGNAL(triggered()),m_dlgAbout,SLOT(show())); m_dlgModbusRTU = new SettingsModbusRTU(this,m_modbusCommSettings); connect(ui->actionSerial_RTU,SIGNAL(triggered()),this,SLOT(showSettingsModbusRTU())); m_dlgModbusTCP = new SettingsModbusTCP(this,m_modbusCommSettings); connect(ui->actionTCP,SIGNAL(triggered()),this,SLOT(showSettingsModbusTCP())); m_dlgSettings = new Settings(this,m_modbusCommSettings); connect(ui->actionSettings,SIGNAL(triggered()),this,SLOT(showSettings())); m_busMonitor = new BusMonitor(this, m_modbus->rawModel); connect(ui->actionBus_Monitor,SIGNAL(triggered()),this,SLOT(showBusMonitor())); //UI - connections connect(ui->cmbModbusMode,SIGNAL(currentIndexChanged(int)),this,SLOT(changedModbusMode(int))); connect(ui->cmbFunctionCode,SIGNAL(currentIndexChanged(int)),this,SLOT(changedFunctionCode(int))); connect(ui->cmbBase,SIGNAL(currentIndexChanged(int)),this,SLOT(changedBase(int))); connect(ui->cmbStartAddrBase,SIGNAL(currentIndexChanged(int)),this,SLOT(changedStartAddrBase(int))); connect(ui->sbSlaveID,SIGNAL(valueChanged(int)),this,SLOT(changedSlaveID(int))); connect(ui->sbNoOfRegs,SIGNAL(valueChanged(int)),this,SLOT(changedNoOfRegs(int))); connect(ui->sbStartAddress,SIGNAL(valueChanged(int)),this,SLOT(changedStartAddress(int))); connect(ui->spInterval,SIGNAL(valueChanged(int)),this,SLOT(changedScanRate(int))); connect(ui->actionClear,SIGNAL(triggered()),this,SLOT(clearItems())); connect(ui->actionRead_Write,SIGNAL(triggered()),this,SLOT(request())); connect(ui->actionScan,SIGNAL(toggled(bool)),this,SLOT(scan(bool))); connect(ui->actionConnect,SIGNAL(toggled(bool)),this,SLOT(changedConnect(bool))); connect(ui->actionReset_Counters,SIGNAL(triggered()),this,SIGNAL(resetCounters())); connect(ui->actionOpenLogFile,SIGNAL(triggered()),this,SLOT(openLogFile())); connect(ui->actionModbus_Manual,SIGNAL(triggered()),this,SLOT(openModbusManual())); connect(ui->actionEnglish_en_US,SIGNAL(triggered()),this,SLOT(changeLanguage())); connect(ui->actionSimplified_Chinese_zh_CN,SIGNAL(triggered()),this,SLOT(changeLanguage())); connect(ui->actionTraditional_Chinese_zh_TW,SIGNAL(triggered()),this,SLOT(changeLanguage())); connect(ui->actionLoad_Session,SIGNAL(triggered(bool)),this,SLOT(loadSession())); connect(ui->actionSave_Session,SIGNAL(triggered(bool)),this,SLOT(saveSession())); //UI - status m_statusInd = new QLabel; m_statusInd->setFixedSize( 16, 16 ); m_statusText = new QLabel; m_baseAddr = new QLabel(tr("Base Addr : ") "0"); m_statusPackets = new QLabel(tr("Packets : ") "0"); m_statusPackets->setStyleSheet("QLabel {color:blue;}"); m_statusErrors = new QLabel(tr("Errors : ") "0"); m_statusErrors->setStyleSheet("QLabel {color:red;}"); ui->statusBar->addWidget(m_statusInd); ui->statusBar->addWidget(m_statusText, 10); ui->statusBar->addWidget(m_baseAddr, 10); ui->statusBar->addWidget(m_statusPackets, 10); ui->statusBar->addWidget(m_statusErrors, 10); m_statusInd->setPixmap(QPixmap(":/img/ballorange-16.png")); //Setup Toolbar ui->mainToolBar->addAction(ui->actionLoad_Session); ui->mainToolBar->addAction(ui->actionSave_Session); ui->mainToolBar->addAction(ui->actionConnect); ui->mainToolBar->addAction(ui->actionRead_Write); ui->mainToolBar->addAction(ui->actionScan); ui->mainToolBar->addAction(ui->actionClear); ui->mainToolBar->addAction(ui->actionReset_Counters); ui->mainToolBar->addSeparator(); ui->mainToolBar->addAction(ui->actionOpenLogFile); ui->mainToolBar->addAction(ui->actionBus_Monitor); ui->mainToolBar->addSeparator(); ui->mainToolBar->addAction(ui->actionSerial_RTU); ui->mainToolBar->addAction(ui->actionTCP); ui->mainToolBar->addAction(ui->actionSettings); ui->mainToolBar->addSeparator(); ui->mainToolBar->addAction(ui->actionModbus_Manual); ui->mainToolBar->addAction(ui->actionAbout); ui->mainToolBar->addAction(ui->actionExit); //Init models ui->tblRegisters->setItemDelegate(m_modbus->regModel->itemDelegate()); ui->tblRegisters->setModel(m_modbus->regModel->model); changedBase(m_modbusCommSettings->base()); m_modbus->regModel->setStartAddrBase(10); clearItems();//init model ui //Update UI updateStatusBar(); refreshView(); //Logging level QsLogging::Logger::instance().setLoggingLevel((QsLogging::Level)m_modbusCommSettings->loggingLevel()); QLOG_INFO()<< "Start Program" ; } MainWindow::~MainWindow() { if (m_modbus) m_modbus->modbusDisConnect(); delete ui; QLOG_INFO()<< "Stop Program" ; } void MainWindow::showSettingsModbusRTU() { //Show RTU Settings Dialog if (m_dlgModbusRTU->exec()==QDialog::Accepted) { QLOG_TRACE()<< "RTU settings changes accepted "; updateStatusBar(); m_modbusCommSettings->saveSettings(); } else QLOG_WARN()<< "RTU settings changes rejected "; } void MainWindow::showSettingsModbusTCP() { //Show TCP Settings Dialog if (m_dlgModbusTCP->exec()==QDialog::Accepted) { QLOG_TRACE()<< "TCP settings changes accepted "; updateStatusBar(); m_modbusCommSettings->saveSettings(); } else QLOG_WARN()<< "TCP settings changes rejected "; } void MainWindow::showSettings() { //Show General Settings Dialog if (m_dlgSettings->exec()==QDialog::Accepted) { QLOG_TRACE()<< "Settings changes accepted "; m_modbus->rawModel->setMaxNoOfLines(m_modbusCommSettings->maxNoOfLines().toInt()); m_modbus->setTimeOut(m_modbusCommSettings->timeOut().toInt()); m_modbusCommSettings->saveSettings(); } else QLOG_WARN()<< "Settings changes rejected "; updateStatusBar(); } void MainWindow::showBusMonitor() { //Show Bus Monitor m_modbus->rawModel->setMaxNoOfLines(m_modbusCommSettings->maxNoOfLines().toInt()); m_busMonitor->move(this->x() this->width() 20, this->y()); m_busMonitor->show(); } void MainWindow::changedModbusMode(int currIndex) { //Change lblSlave text : Slave Addr, Unit ID QLOG_TRACE()<< "Modbus Mode changed. Index = " << currIndex; m_modbusCommSettings->setModbusMode(currIndex); m_modbusCommSettings->saveSettings(); if (currIndex == 0) { //RTU ui->lblSlave->setText("Slave Addr"); } else { //TCP ui->lblSlave->setText("Unit ID"); } updateStatusBar(); } void MainWindow::changedFunctionCode(int currIndex) { //Enable-Disable number of coils or registers QLOG_TRACE()<< "Function Code changed. Index = " << currIndex; m_modbusCommSettings->setFunctionCode(currIndex); m_modbusCommSettings->saveSettings(); const int functionCode = EUtils::ModbusFunctionCode(currIndex); QString String_number_of_coils(tr("Number of Coils")); QString String_number_of_inputs(tr("Number of Inputs")); QString String_number_of_registers(tr("Number of Registers")); switch(functionCode)//Label = Read Request, Write Request { case MODBUS_FC_READ_COILS: m_modbus->regModel->setIs16Bit(false); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_coils); break; case MODBUS_FC_READ_DISCRETE_INPUTS: m_modbus->regModel->setIs16Bit(false); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_inputs); break; case MODBUS_FC_READ_HOLDING_REGISTERS: m_modbus->regModel->setIs16Bit(true); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_registers); break; case MODBUS_FC_READ_INPUT_REGISTERS: m_modbus->regModel->setIs16Bit(true); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_registers); break; case MODBUS_FC_WRITE_SINGLE_COIL: m_modbus->regModel->setIs16Bit(false); ui->sbNoOfRegs->setValue(1); ui->sbNoOfRegs->setEnabled(false); ui->lblNoOfCoils->setText(String_number_of_coils); break; case MODBUS_FC_WRITE_MULTIPLE_COILS: m_modbus->regModel->setIs16Bit(false); if (ui->sbNoOfRegs->value() < 2) ui->sbNoOfRegs->setValue(2); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_coils); break; case MODBUS_FC_WRITE_SINGLE_REGISTER: m_modbus->regModel->setIs16Bit(true); ui->sbNoOfRegs->setValue(1); ui->sbNoOfRegs->setEnabled(false); ui->lblNoOfCoils->setText(String_number_of_registers); break; case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: m_modbus->regModel->setIs16Bit(true); if (ui->sbNoOfRegs->value() < 2) ui->sbNoOfRegs->setValue(2); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_registers); break; default: m_modbus->regModel->setIs16Bit(false); ui->sbNoOfRegs->setValue(1); ui->sbNoOfRegs->setEnabled(true); ui->lblNoOfCoils->setText(String_number_of_coils); break; } m_modbus->setNumOfRegs(ui->sbNoOfRegs->value()); addItems(); } void MainWindow::changedBase(int currIndex) { //Change Base QLOG_TRACE()<< "Base changed. Index = " << currIndex; m_modbusCommSettings->setBase(currIndex); m_modbusCommSettings->saveSettings(); switch(currIndex) { case 0: m_modbus->regModel->setBase(EUtils::Bin); break; case 1: m_modbus->regModel->setBase(EUtils::UInt); break; case 2: m_modbus->regModel->setBase(EUtils::Hex); break; default: m_modbus->regModel->setBase(EUtils::UInt); break; } } void MainWindow::changedScanRate(int value) { //Enable-Disable Time Interval QLOG_TRACE()<< "ScanRate changed. Value = " << value; m_modbusCommSettings->setScanRate(value); m_modbusCommSettings->saveSettings(); m_modbus->setScanRate(value); } void MainWindow::changedConnect(bool value) { //Connect - Disconnect if (value) { //Connected modbusConnect(true); QLOG_INFO()<< "Connected "; } else { //Disconnected modbusConnect(false); QLOG_INFO()<< "Disconnected "; } m_modbus->resetCounters(); refreshView(); } void MainWindow::changedSlaveID(int value) { //Slave ID QLOG_TRACE()<< "Slave ID Changed. Value = " << value; m_modbusCommSettings->setSlaveID(value); m_modbusCommSettings->saveSettings(); } void MainWindow::openLogFile() { //Open log file QString arg; QLOG_TRACE()<< "Open log file"; arg = "file:///" QCoreApplication::applicationDirPath() "/QModMaster.log"; QDesktopServices::openUrl(QUrl(arg)); } void MainWindow::openModbusManual() { //Open Modbus Manual QString arg; QLOG_TRACE()<< "Open Modbus Manual"; arg = "file:///" QCoreApplication::applicationDirPath() "/ManModbus/index.html"; QDesktopServices::openUrl(QUrl(arg)); } void MainWindow::changedStartAddrBase(int currIndex) { //Change Base QLOG_TRACE()<< "Start Addr Base changed. Index = " << currIndex; switch(currIndex) { case 0: ui->sbStartAddress->setDisplayIntegerBase(10); m_modbus->regModel->setStartAddrBase(10); break; case 1: ui->sbStartAddress->setDisplayIntegerBase(16); m_modbus->regModel->setStartAddrBase(16); break; default: ui->sbStartAddress->setDisplayIntegerBase(10); m_modbus->regModel->setStartAddrBase(10); break; } } void MainWindow::changedStartAddress(int value) { //Start Address changed QLOG_TRACE()<< "Start Address changed. Value = " << value; m_modbusCommSettings->setStartAddr(value); m_modbusCommSettings->saveSettings(); m_modbus->setStartAddr(value); addItems(); } void MainWindow::changedNoOfRegs(int value) { //No of regs changed QLOG_TRACE()<< "No Of Regs changed. Value = " << value; m_modbusCommSettings->setNoOfRegs(value); m_modbusCommSettings->saveSettings(); m_modbus->setNumOfRegs(value); addItems(); } void MainWindow::updateStatusBar() { //Update status bar QString msg; if(ui->cmbModbusMode->currentIndex() == 0) { //RTU msg = "RTU : "; msg = m_modbusCommSettings->serialPortName() " | "; msg = m_modbusCommSettings->baud() ","; msg = m_modbusCommSettings->dataBits() ","; msg = m_modbusCommSettings->stopBits() ","; msg = m_modbusCommSettings->parity(); } else { msg = "TCP : "; msg = m_modbusCommSettings->slaveIP() ":"; msg = m_modbusCommSettings->TCPPort(); } m_statusText->clear(); m_statusText->setText(msg); //Connection is valid if (m_modbus->isConnected()) { m_statusInd->setPixmap(QPixmap(":/icons/bullet-green-16.png")); } else { m_statusInd->setPixmap(QPixmap(":/icons/bullet-red-16.png")); } //basr Address m_baseAddr->setText("Base Addr : " m_modbusCommSettings->baseAddr()); } void MainWindow::addItems() { //add items m_modbus->setSlave(ui->sbSlaveID->value()); m_modbus->setFunctionCode(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex())); m_modbus->setStartAddr(ui->sbStartAddress->value()); m_modbus->setNumOfRegs(ui->sbNoOfRegs->value()); QLOG_INFO()<< "Add Items. Function Code = " << QString::number(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex()),16); m_modbus->addItems(); } void MainWindow::clearItems() { //Clear items from registers model QLOG_TRACE()<< "clearItems" ; m_modbus->regModel->clear(); addItems(); } void MainWindow::request() { //Request items from modbus adapter and add raw data to raw data model int rowCount = m_modbus->regModel->model->rowCount(); int baseAddr; QLOG_TRACE()<< "Request transaction. No or registers = " << rowCount; if (rowCount == 0) { mainWin->showUpInfoBar(tr("Request failed\nAdd items to Registers Table."), InfoBar::Error); QLOG_WARN()<< "Request failed. No items in registers table "; return; } else { mainWin->hideInfoBar(); } //get base address baseAddr = m_modbusCommSettings->baseAddr().toInt(); m_modbus->setSlave(ui->sbSlaveID->value()); m_modbus->setFunctionCode(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex())); m_modbus->setStartAddr(ui->sbStartAddress->value() baseAddr); m_modbus->setNumOfRegs(ui->sbNoOfRegs->value()); //Modbus data m_modbus->modbusTransaction(); } void MainWindow::scan(bool value) { //Request items from modbus adapter and add raw data to raw data model int rowCount = m_modbus->regModel->model->rowCount(); int baseAddr; if (value && rowCount == 0) { mainWin->showUpInfoBar(tr("Request failed\nAdd items to Registers Table."), InfoBar::Error); QLOG_WARN()<< "Request failed. No items in registers table "; ui->actionScan->setChecked(false); return; } else { mainWin->hideInfoBar(); } //get base address baseAddr = m_modbusCommSettings->baseAddr().toInt(); m_modbus->setSlave(ui->sbSlaveID->value()); m_modbus->setFunctionCode(EUtils::ModbusFunctionCode(ui->cmbFunctionCode->currentIndex())); m_modbus->setStartAddr(ui->sbStartAddress->value() baseAddr); m_modbus->setNumOfRegs(ui->sbNoOfRegs->value()); //Start-Stop poll timer QLOG_TRACE()<< "Scan time = " << value; if (value){ if (ui->spInterval->value() < m_modbusCommSettings->timeOut().toInt() * 1000 * 2){ mainWin->showUpInfoBar(tr("Scan rate should be at least 2 * Timeout."), InfoBar::Error); QLOG_ERROR()<< "Scan rate error. should be at least 2 * Timeout "; } else { m_modbus->setScanRate(ui->spInterval->value()); m_modbus->startPollTimer(); } } else m_modbus->stopPollTimer(); //Update UI ui->cmbBase->setEnabled(!value); ui->cmbFunctionCode->setEnabled(!value); ui->sbSlaveID->setEnabled(!value); ui->sbStartAddress->setEnabled(!value); ui->spInterval->setEnabled(!value); ui->cmbStartAddrBase->setEnabled(!value); if (!value) changedFunctionCode(ui->cmbFunctionCode->currentIndex()); else ui->sbNoOfRegs->setEnabled(false); } void MainWindow::modbusConnect(bool connect) { //Modbus connect - RTU/TCP QLOG_TRACE()<< "Modbus Connect. Value = " << connect; if (connect) { //RTU if (ui->cmbModbusMode->currentIndex() == EUtils::RTU) { m_modbus->setSlave(ui->sbSlaveID->value()); m_modbus->modbusConnectRTU(m_modbusCommSettings->serialPortName(), m_modbusCommSettings->baud().toInt(), EUtils::parity(m_modbusCommSettings->parity()), m_modbusCommSettings->dataBits().toInt(), m_modbusCommSettings->stopBits().toInt(), m_modbusCommSettings->RTS().toInt(), m_modbusCommSettings->timeOut().toInt() ); } else { //TCP m_modbus->modbusConnectTCP(m_modbusCommSettings->slaveIP(), m_modbusCommSettings->TCPPort().toInt(), m_modbusCommSettings->timeOut().toInt()); } } else { //Disconnect m_modbus->modbusDisConnect(); ui->actionScan->setChecked(false); } updateStatusBar(); //Update UI ui->actionLoad_Session->setEnabled(!m_modbus->isConnected()); ui->actionSave_Session->setEnabled(!m_modbus->isConnected()); ui->actionConnect->setChecked(m_modbus->isConnected()); ui->actionRead_Write->setEnabled(m_modbus->isConnected()); ui->actionScan->setEnabled(m_modbus->isConnected()); ui->cmbModbusMode->setEnabled(!m_modbus->isConnected()); } void MainWindow::refreshView() { QLOG_TRACE()<< "Packets sent / received = " << m_modbus->packets() << ", errors = " << m_modbus->errors(); ui->tblRegisters->resizeColumnsToContents(); m_statusPackets->setText(tr("Packets : ") QString("%1").arg(m_modbus->packets())); m_statusErrors->setText(tr("Errors : ") QString("%1").arg(m_modbus->errors())); } void MainWindow::loadSession() { QString fName; QLOG_TRACE()<< "load session"; fName = QFileDialog::getOpenFileName(this, "Load Session file", "", "Session Files (*.ses);;All Files (*.*)"); //check if (fName != ""){ m_modbusCommSettings->loadSession(fName); //Update UI ui->sbStartAddress->setMinimum(m_modbusCommSettings->baseAddr().toInt()); ui->cmbBase->setCurrentIndex(m_modbusCommSettings->base()); ui->cmbFunctionCode->setCurrentIndex(m_modbusCommSettings->functionCode()); ui->cmbModbusMode->setCurrentIndex(m_modbusCommSettings->modbusMode()); ui->sbSlaveID->setValue(m_modbusCommSettings->slaveID()); ui->spInterval->setValue(m_modbusCommSettings->scanRate()); ui->sbStartAddress->setValue(m_modbusCommSettings->startAddr()); ui->sbNoOfRegs->setValue(m_modbusCommSettings->noOfRegs()); updateStatusBar(); refreshView(); QMessageBox::information(this, "QModMaster", "Load session file : " fName); } else QMessageBox::information(this, "QModMaster", "Cancel operation Or no file selected"); } void MainWindow::saveSession() { QString fName; QLOG_TRACE()<< "save session"; fName = QFileDialog::getSaveFileName(this, "Save Session file", "", "Session Files (*.ses)"); //check if (fName != ""){ m_modbusCommSettings->saveSession(fName); QMessageBox::information(this, "QModMaster", "Save session file : " fName); } else QMessageBox::information(this, "QModMaster", "Cancel operation Or no file selected"); } void MainWindow::showUpInfoBar(QString message, InfoBar::InfoType type) { ui->infobar->show(message, type); } void MainWindow::hideInfoBar() { ui->infobar->hide(); } void MainWindow::changeEvent(QEvent* event) { if(event->type() == QEvent::LanguageChange) { ui->retranslateUi(this); } QMainWindow::changeEvent(event); } void MainWindow::changeLanguage() { extern QTranslator *Translator; QCoreApplication::removeTranslator(Translator); Translator->load(":/translations/" QCoreApplication::applicationName() sender()->objectName().right(6)); QCoreApplication::installTranslator(Translator); }
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论