Changeset - 3d74de1a88e6
[Not reviewed]
Merge default
0 4 5
Hasan Yavuz ÖZDERYA - 10 years ago 2015-09-13 10:43:10
hy@ozderya.net
Merge with portlist
9 files changed with 257 insertions and 67 deletions:
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -51,8 +51,9 @@ endif (QWT_USE_STATIC)
 
# includes
 
include_directories(${QWT_INCLUDE_DIR})
 

	
 
# wrap UI files
 
# wrap UI and resource files
 
qt5_wrap_ui(UI_FILES mainwindow.ui portcontrol.ui about_dialog.ui)
 
qt5_add_resources(RES_FILES misc/icons.qrc)
 

	
 
add_executable(${PROGRAM_NAME} WIN32
 
  main.cpp
 
@@ -64,7 +65,9 @@ add_executable(${PROGRAM_NAME} WIN32
 
  framebuffer.cpp
 
  scalepicker.cpp
 
  scalezoomer.cpp
 
  portlist.cpp
 
  ${UI_FILES}
 
  ${RES_FILES}
 
  misc/windows_icon.rc
 
  )
 

	
misc/bluetooth_icon.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
misc/icons.qrc
Show inline comments
 
new file 100644
 
<RCC>
 
    <qresource prefix="/">
 
        <file>usb_icon.png</file>
 
        <file>bluetooth_icon.png</file>
 
    </qresource>
 
</RCC>
misc/usb_icon.png
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
portcontrol.cpp
Show inline comments
 
@@ -22,6 +22,7 @@
 

	
 
#include <QSerialPortInfo>
 
#include <QKeySequence>
 
#include <QLabel>
 
#include <QtDebug>
 
#include "utils.h"
 

	
 
@@ -41,24 +42,33 @@ PortControl::PortControl(QSerialPort* po
 
    openAction.setToolTip("Open Port (F2)");
 
    QObject::connect(&openAction, &QAction::triggered,
 
                     this, &PortControl::openActionTriggered);
 

	
 
    portToolBar.addWidget(&tbPortList);
 
    portToolBar.addAction(&openAction);
 

	
 
    // setup port selection widgets
 
    tbPortList.setModel(&portList);
 
    ui->cbPortList->setModel(&portList);
 
    QObject::connect(ui->cbPortList,
 
                     SELECT<int>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::onCbPortListActivated);
 
    QObject::connect(&tbPortList,
 
                     SELECT<int>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::onTbPortListActivated);
 
    QObject::connect(ui->cbPortList,
 
                     SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::selectPort);
 
    QObject::connect(&tbPortList,
 
                     SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::selectPort);
 

	
 
    // setup buttons
 
    QObject::connect(ui->pbReloadPorts, &QPushButton::clicked,
 
                     this, &PortControl::loadPortList);
 

	
 
    ui->pbOpenPort->setDefaultAction(&openAction);
 

	
 
    // TODO: port name coming from combobox is dirty, create a separate layer of signals
 
    //       that will sanitize this information
 
    QObject::connect(ui->cbPortList,
 
                     SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::selectPort);
 

	
 
    QObject::connect(ui->cbPortList,
 
                     SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::onPortNameChanged);
 

	
 
    // setup baud rate selection widget
 
    QObject::connect(ui->cbBaudRate,
 
                     SELECT<const QString&>::OVERLOAD_OF(&QComboBox::activated),
 
                     this, &PortControl::selectBaudRate);
 
@@ -118,36 +128,13 @@ PortControl::~PortControl()
 

	
 
void PortControl::loadPortList()
 
{
 
    QString currentSelection = ui->cbPortList->currentText();
 

	
 
    ui->cbPortList->clear();
 

	
 
    discoveredPorts.clear();
 
    for (auto port : QSerialPortInfo::availablePorts())
 
    QString currentSelection = ui->cbPortList->currentData(PortNameRole).toString();
 
    portList.loadPortList();
 
    int index = portList.indexOf(currentSelection);
 
    if (index >= 0)
 
    {
 
        QString pName = port.portName();
 
        if (!port.description().isEmpty()) pName += QString(" ") + port.description();
 
        if (port.hasProductIdentifier())
 
        {
 
            QString vID = QString("%1").arg(port.vendorIdentifier(), 4, 16, QChar('0'));
 
            QString pID = QString("%1").arg(port.productIdentifier(), 4, 16, QChar('0'));
 
            pName = pName + " [" + vID + ":" + pID + "]";
 
        }
 
        ui->cbPortList->addItem(pName);
 
        discoveredPorts << port.portName();
 
    }
 

	
 
    ui->cbPortList->addItems(userEnteredPorts);
 

	
 
    // find current selection in the new list, maybe it doesn't exist anymore?
 
    int currentSelectionIndex = ui->cbPortList->findText(currentSelection);
 
    if (currentSelectionIndex >= 0)
 
    {
 
        ui->cbPortList->setCurrentIndex(currentSelectionIndex);
 
    }
 
    else // our port doesn't exist anymore, close port if it's open
 
    {
 
        if (serialPort->isOpen()) togglePort();
 
        ui->cbPortList->setCurrentIndex(index);
 
        tbPortList.setCurrentIndex(index);
 
    }
 
}
 

	
 
@@ -230,11 +217,26 @@ void PortControl::togglePort()
 
    }
 
    else
 
    {
 
        // port name may contain description
 
        QString portName = ui->cbPortList->currentText().split(" ")[0];
 
        keepPortName(portName);
 
        // we get the port name from the edit text, which may not be
 
        // in the portList if user hasn't pressed Enter
 
        // Also note that, portText may not be the `portName`
 
        QString portText = ui->cbPortList->currentText();
 
        QString portName;
 
        int portIndex = portList.indexOf(portText);
 
        if (portIndex < 0) // not in list, add to model and update the selections
 
        {
 
            portList.appendRow(new PortListItem(portText));
 
            ui->cbPortList->setCurrentIndex(portList.rowCount()-1);
 
            tbPortList.setCurrentIndex(portList.rowCount()-1);
 
            portName = portText;
 
        }
 
        else
 
        {
 
            // get the port name from the data field
 
            portName = static_cast<PortListItem*>(portList.item(portIndex))->portName();
 
        }
 

	
 
        serialPort->setPortName(portName);
 
        serialPort->setPortName(ui->cbPortList->currentData(PortNameRole).toString());
 

	
 
        // open port
 
        if (serialPort->open(QIODevice::ReadWrite))
 
@@ -276,24 +278,6 @@ void PortControl::enableSkipByte(bool en
 
    ui->pbSkipByte->setDisabled(enabled);
 
}
 

	
 
void PortControl::keepPortName(QString portName)
 
{
 
    if(!discoveredPorts.contains(portName) &&
 
       !userEnteredPorts.contains(portName))
 
    {
 
        userEnteredPorts << portName;
 
    }
 
    if(ui->cbPortList->findText(portName) < 0)
 
    {
 
        ui->cbPortList->addItem(portName);
 
    }
 
}
 

	
 
void PortControl::onPortNameChanged(QString portName)
 
{
 
    keepPortName(portName);
 
}
 

	
 
QToolBar* PortControl::toolBar()
 
{
 
    return &portToolBar;
 
@@ -303,3 +287,13 @@ void PortControl::openActionTriggered(bo
 
{
 
    togglePort();
 
}
 

	
 
void PortControl::onCbPortListActivated(int index)
 
{
 
    tbPortList.setCurrentIndex(index);
 
}
 

	
 
void PortControl::onTbPortListActivated(int index)
 
{
 
    ui->cbPortList->setCurrentIndex(index);
 
}
portcontrol.h
Show inline comments
 
@@ -26,6 +26,9 @@
 
#include <QStringList>
 
#include <QToolBar>
 
#include <QAction>
 
#include <QComboBox>
 

	
 
#include "portlist.h"
 

	
 
namespace Ui {
 
class PortControl;
 
@@ -53,10 +56,8 @@ private:
 

	
 
    QToolBar portToolBar;
 
    QAction openAction;
 

	
 
    QStringList discoveredPorts; // list of port names returned by availablePorts
 
    QStringList userEnteredPorts; // list of port names entered by user
 
    void keepPortName(QString portName); // if it's not already in userEn. or discv. list
 
    QComboBox tbPortList;
 
    PortList portList;
 

	
 
public slots:
 
    void loadPortList();
 
@@ -72,9 +73,11 @@ public slots:
 
    void selectFlowControl(int flowControl); // flowControl must be one of QSerialPort::FlowControl
 

	
 
private slots:
 
    void onPortNameChanged(QString portName);
 
    void openActionTriggered(bool checked);
 

	
 
    void onCbPortListActivated(int index);
 
    void onTbPortListActivated(int index);
 

	
 
signals:
 
    void skipByteRequested();
 
    void portToggled(bool open);
portlist.cpp
Show inline comments
 
new file 100644
 
/*
 
  Copyright © 2015 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot 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 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot 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 serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include <QVariant>
 
#include <QIcon>
 
#include <QtDebug>
 

	
 
#include "portlist.h"
 

	
 
PortListItem::PortListItem(QString name, QString description, quint16 vid, quint16 pid)
 
{
 
    construct(name, description, vid, pid);
 
}
 

	
 
PortListItem::PortListItem(QSerialPortInfo* portInfo)
 
{
 
    if (portInfo->hasProductIdentifier())
 
    {
 
        construct(portInfo->portName(),
 
                  portInfo->description(),
 
                  portInfo->vendorIdentifier(),
 
                  portInfo->productIdentifier());
 
    }
 
    else
 
    {
 
        construct(portInfo->portName());
 
    }
 
}
 

	
 
void PortListItem::construct(QString name, QString description, quint16 vid, quint16 pid)
 
{
 
    QString text = name;
 
    if (!description.isEmpty())
 
    {
 
        text += QString(" ") + description;
 
    }
 
    if (vid && pid)
 
    {
 
        text += QString("[%1:").arg(vid, 4, 16, QChar('0'));
 
        text += QString("%1]").arg(pid, 4, 16, QChar('0'));
 
        setIcon(QIcon(":/usb_icon.png"));
 
    }
 
    else if (name.contains("rfcomm"))
 
    {
 
        setIcon(QIcon(":/bluetooth_icon.png"));
 
    }
 
    setText(text);
 
    setData(name, PortNameRole);
 
}
 

	
 
QString PortListItem::portName()
 
{
 
    return data(PortNameRole).toString();
 
}
 

	
 
PortList::PortList(QObject* parent) :
 
    QStandardItemModel(parent)
 
{
 
    loadPortList();
 

	
 
    // we have to use macro based notation to be able to disconnect
 
    QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
 
                     this, SLOT(onRowsInserted(QModelIndex, int, int)));
 
}
 

	
 
void PortList::loadPortList()
 
{
 
    clear();
 

	
 
    disconnect(this, SLOT(onRowsInserted(QModelIndex,int,int)));
 
    for (auto portInfo : QSerialPortInfo::availablePorts())
 
    {
 
        appendRow(new PortListItem(&portInfo));
 
    }
 
    for (auto portName : userEnteredPorts)
 
    {
 
        appendRow(new PortListItem(portName));
 
    }
 
    QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
 
                     this, SLOT(onRowsInserted(QModelIndex, int, int)));
 
}
 

	
 
int PortList::indexOf(QString portText)
 
{
 
    for (int i = 0; i < rowCount(); i++)
 
    {
 
        if (item(i)->text() == portText)
 
        {
 
            return i;
 
        }
 
    }
 
    return -1; // not found
 
}
 

	
 
void PortList::onRowsInserted(QModelIndex parent, int start, int end)
 
{
 
    PortListItem* newItem = static_cast<PortListItem*>(item(start));
 
    QString portName = newItem->text();
 
    newItem->setData(portName, PortNameRole);
 
    userEnteredPorts << portName;
 
}
portlist.h
Show inline comments
 
new file 100644
 
/*
 
  Copyright © 2015 Hasan Yavuz Özderya
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot 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 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot 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 serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#ifndef PORTLIST_H
 
#define PORTLIST_H
 

	
 
#include <QStandardItemModel>
 
#include <QStandardItem>
 
#include <QList>
 
#include <QSerialPortInfo>
 

	
 
enum PortListRoles
 
{
 
    PortNameRole = Qt::UserRole+1  // portName as QString
 
};
 

	
 
class PortListItem : public QStandardItem
 
{
 
public:
 
    PortListItem(QString name, QString description="", quint16 vid=0, quint16 pid=0);
 
    PortListItem(QSerialPortInfo* portInfo);
 

	
 
    QString portName(); // returns only the port name
 

	
 
private:
 
    // common constructor
 
    void construct(QString name, QString description="", quint16 vid=0, quint16 pid=0);
 
};
 

	
 
class PortList : public QStandardItemModel
 
{
 
    Q_OBJECT
 
public:
 
    PortList(QObject* parent=0);
 

	
 
    void loadPortList();
 
    int indexOf(QString portText); // return -1 if not found
 

	
 
private:
 
    QStringList userEnteredPorts;
 

	
 
private slots:
 
    void onRowsInserted(QModelIndex parent, int start, int end);
 
};
 

	
 
#endif // PORTLIST_H
serialplot.pro
Show inline comments
 
@@ -42,6 +42,7 @@ SOURCES += main.cpp\
 
    framebuffer.cpp \
 
    scalepicker.cpp \
 
    scalezoomer.cpp
 
    portlist.cpp
 

	
 
HEADERS  += mainwindow.h \
 
    utils.h \
 
@@ -53,6 +54,7 @@ HEADERS  += mainwindow.h \
 
    framebuffer.h \
 
    scalepicker.h \
 
    scalezoomer.h
 
    portlist.h
 

	
 
FORMS    += mainwindow.ui \
 
    about_dialog.ui \
 
@@ -61,3 +63,6 @@ FORMS    += mainwindow.ui \
 
INCLUDEPATH += qmake/
 

	
 
CONFIG += c++11
 

	
 
RESOURCES += \
 
    misc/icons.qrc
0 comments (0 inline, 0 general)