关于wpa_supplicant这块的代码,基本可以参考https://blog.csdn.net/Dr_Abel/article/details/51335599,对其中做了部分的修改。
主要是记录一下Qt的模型/视图编程,可以先看一下演示效果:
主要的wifi参数有强度 ,ssid,与连接状态,数据的显示时使用QTableview显示,采用模型/视频编程,下面上这部分代码
mainwindow界面代码:
#include "../NetworkManager/passworddialog.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
my_model = new WifiModel(this);
mydelete = new ButtonDelegate(this);
connect(mydelete,&ButtonDelegate::buttonclicked,this,&MainWindow::showpasswordDialg);
connect(instance,&NetworkManager::sigRefreshed,my_model,&WifiModel::refrushModel);
ui->wifitableView->setModel(my_model);
ui->wifitableView->setItemDelegateForColumn(2,mydelete);
ui->wifitableView->show();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showpasswordDialg(QString bssid)
{
QDialog *d = new PasswordDialog(this,bssid);
d->setWindowModality(Qt::WindowModal);
d->show();
}
这部分代码很好理解,通过给wifitableview部件设置数据模型my_model,与将Tableview表中的第三列委托成按键控件ButtonDelegate,使其能够通过按钮控件患处QDialog窗口,通过内部lineEdit唤出输入法插件,这里用的是goole的一个输入法插件。
my_model部分代码:
#include "wifimodel.h"
WifiModel::WifiModel(QObject *parent)
: QAbstractTableModel(parent)
{
m_header<<tr("强度")<<tr("名称")<<tr("状态");
}
QVariant WifiModel::headerData(int section, Qt::Orientation orientation, int role) const
{
// FIXME: Implement me!
if(role==Qt::DisplayRole&&orientation==Qt::Horizontal)
{
return m_header[section];
}
return QAbstractTableModel::headerData(section,orientation,role);
}
int WifiModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
//return 3;
return instance->wifiList().size();
}
int WifiModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return 3;
}
QVariant WifiModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if(role == Qt::DisplayRole)
{
QString value;
switch (index.column()) {
case 0:
value = instance->wifiList().operator[](index.row()).operator[](ESSID_SIGNAL);
break;
case 1:
value = instance->wifiList().operator[](index.row()).operator[](ESSID_NAME);
break;
default:
break;
}
return value;
}
return QVariant();
}
void WifiModel::refrushModel()
{
beginResetModel();
endResetModel();
}
关于model这块,其中headerData是表头函数,用于配置表格的表头,这里用三列,m_header<<tr("强度")<<tr("名称")<<tr("状态");rowCount与columnCount返回行列与竖列,其中竖列就是插入的表头个数,行列数是通过wpa_supplicant代码模块搜索到的wifi个数。
data函数尤为重要,用于精确的返回表中显示的数据。其中refrushModel用于刷新数据,主要是刷新界面使用。
关于delegate部分的代码
#include "buttondelegate.h"
#include <QDebug>
#include <QMouseEvent>
#include <QDialog>
#include <QDesktopWidget>
#include "passworddialog.h"
const int FILE_OPERATE_COLUMN = 2;//按键所在列
ButtonDelegate::ButtonDelegate(QObject *parent) :
QItemDelegate(parent)
{
}
ButtonDelegate::~ButtonDelegate()
{
QMap<QModelIndex, QStyleOptionButton*>::iterator it;
for (it = m_btns.begin();it != m_btns.end(); it++)
{
if(it.value() != nullptr)
{
delete it.value();
it.value() = nullptr;
}
}
}
void ButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//在特定的索引处绘制按键,这个变量临时存储绘制的按键信息
QStyleOptionButton* button = m_btns.value(index);
//如果为按键列绘制按键
if (index.column() == FILE_OPERATE_COLUMN) {
//进行判断,如果是Map容器中没有,则为它动态分配内存
if(button == nullptr)
{
button = new QStyleOptionButton();//绘制存button的参数的对象
button->features = QStyleOptionButton::None;//设置为pushButton类型,可以按下
button->rect = option.rect.adjusted(1, 1, -1, -1);//绘制尺寸
button->state |= QStyle::State_Enabled;
(const_cast<ButtonDelegate *>(this))->m_btns.insert(index, button);//将绘制的按键放入Qmap
}
if(instance->wifiList().operator[](index.row()).operator[](ESSID_STATUS) != "COMPLETED")
{
button->text = tr("连接");
}
else {
button->text = tr("已连接");
}
}
painter->save();
if (option.state & QStyle::State_Selected)
{
painter->fillRect(option.rect, option.palette.highlight());
}
painter->restore();
QApplication::style()->drawControl(QStyle::CE_PushButton, button, painter);
}
bool ButtonDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if (event->type() == QEvent::MouseButtonPress)
{
QMouseEvent* e =(QMouseEvent*)event;
//确定鼠标点击的位置在画的按键中
if (option.rect.adjusted(1, 1, -1, -1).contains(e->x(), e->y()) && m_btns.contains(index))
{
qDebug()<<"--------";
m_btns.value(index)->state |= QStyle::State_Sunken;
}
}
if (event->type() == QEvent::MouseButtonRelease)
{
//qDebug()<<"++++++++";
QMouseEvent* e =(QMouseEvent*)event;
if (option.rect.adjusted(1, 1, -1, -1).contains(e->x(), e->y()) && m_btns.contains(index))
{
m_btns.value(index)->state &= (~QStyle::State_Sunken);
emit buttonclicked(instance->wifiList().operator[](index.row()).operator[](ESSID_BSSID));
}
}
return true;
}
关于Button控件的委托,要想控件一开始就显示在Tableview上,需要重写paint代码,同时对于事件编辑器editorEvent需要重写按键事件。