Imported existing sources
This commit is contained in:
103
.gitignore
vendored
103
.gitignore
vendored
@@ -1,52 +1,73 @@
|
|||||||
# C++ objects and libs
|
# This file is used to ignore files which are generated
|
||||||
*.slo
|
# ----------------------------------------------------------------------------
|
||||||
*.lo
|
|
||||||
*.o
|
*~
|
||||||
|
*.autosave
|
||||||
*.a
|
*.a
|
||||||
*.la
|
*.core
|
||||||
*.lai
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
*.so
|
*.so
|
||||||
*.so.*
|
*.so.*
|
||||||
*.dll
|
*_pch.h.cpp
|
||||||
*.dylib
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
# Qt-es
|
.#*
|
||||||
object_script.*.Release
|
*.*#
|
||||||
object_script.*.Debug
|
core
|
||||||
*_plugin_import.cpp
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
/.qmake.cache
|
/.qmake.cache
|
||||||
/.qmake.stash
|
/.qmake.stash
|
||||||
*.pro.user
|
|
||||||
*.pro.user.*
|
|
||||||
*.qbs.user
|
|
||||||
*.qbs.user.*
|
|
||||||
*.moc
|
|
||||||
moc_*.cpp
|
|
||||||
moc_*.h
|
|
||||||
qrc_*.cpp
|
|
||||||
ui_*.h
|
|
||||||
*.qmlc
|
|
||||||
*.jsc
|
|
||||||
Makefile*
|
|
||||||
*build-*
|
|
||||||
*.qm
|
|
||||||
*.prl
|
|
||||||
|
|
||||||
# Qt unit tests
|
# qtcreator generated files
|
||||||
target_wrapper.*
|
*.pro.user*
|
||||||
|
|
||||||
# QtCreator
|
# xemacs temporary files
|
||||||
*.autosave
|
*.flc
|
||||||
|
|
||||||
# QtCreator Qml
|
# Vim temporary files
|
||||||
*.qmlproject.user
|
.*.swp
|
||||||
*.qmlproject.user.*
|
|
||||||
|
|
||||||
# QtCreator CMake
|
# Visual Studio generated files
|
||||||
CMakeLists.txt.user*
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
# QtCreator 4.8< compilation database
|
# MinGW generated files
|
||||||
compile_commands.json
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
# QtCreator local machine specific files for imported projects
|
|
||||||
*creator.user*
|
|
||||||
|
21
avivpn.pro
Normal file
21
avivpn.pro
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
QT += core gui
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
|
CONFIG += c++17
|
||||||
|
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS QT_DISABLE_DEPRECATED_BEFORE=0x060000
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
entry.cpp \
|
||||||
|
main.cpp \
|
||||||
|
mainwindow.cpp \
|
||||||
|
vpnmodel.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
entry.h \
|
||||||
|
mainwindow.h \
|
||||||
|
vpnmodel.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
mainwindow.ui
|
119
entry.cpp
Normal file
119
entry.cpp
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#include "entry.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
Entry::Entry(const QString &name, const QString &tunnel, bool sudo, QObject *parent) :
|
||||||
|
QObject{parent}, m_name{name}, m_tunnel{tunnel}, m_sudo{sudo}
|
||||||
|
{
|
||||||
|
connect(&m_process, &QProcess::errorOccurred, this, &Entry::errorOccurred);
|
||||||
|
connect(&m_process, &QProcess::stateChanged, this, &Entry::stateChanged);
|
||||||
|
connect(&m_process, &QProcess::readyReadStandardOutput, this, &Entry::readyReadStandardOutput);
|
||||||
|
connect(&m_process, &QProcess::readyReadStandardError, this, &Entry::readyReadStandardError);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry::~Entry()
|
||||||
|
{
|
||||||
|
qDebug() << m_name;
|
||||||
|
m_process.terminate();
|
||||||
|
if (!m_process.waitForFinished(250))
|
||||||
|
m_process.kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::CheckState Entry::state() const
|
||||||
|
{
|
||||||
|
switch (m_process.state())
|
||||||
|
{
|
||||||
|
case QProcess::Starting:
|
||||||
|
return Qt::PartiallyChecked;
|
||||||
|
case QProcess::Running:
|
||||||
|
return Qt::Checked;
|
||||||
|
case QProcess::NotRunning:
|
||||||
|
return Qt::Unchecked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::toggle()
|
||||||
|
{
|
||||||
|
if (m_process.state() == QProcess::NotRunning)
|
||||||
|
start();
|
||||||
|
else
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::start()
|
||||||
|
{
|
||||||
|
qDebug() << m_name;
|
||||||
|
m_logOutput.clear();
|
||||||
|
m_process.start(binaryName(), arguments());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::stop()
|
||||||
|
{
|
||||||
|
qDebug() << m_name;
|
||||||
|
m_process.terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Entry::binaryName() const
|
||||||
|
{
|
||||||
|
return m_sudo ? "sudo" : "ssh";
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Entry::arguments() const
|
||||||
|
{
|
||||||
|
QStringList args {
|
||||||
|
"-v", // Verbose mode. Causes ssh to print debugging messages about its progress.
|
||||||
|
"-N", // Do not execute a remote command. This is useful for just forwarding ports.
|
||||||
|
"-T", // Disable pseudo-terminal allocation.
|
||||||
|
"-oServerAliveInterval=60",
|
||||||
|
"-oExitOnForwardFailure=yes",
|
||||||
|
m_tunnel,
|
||||||
|
"pc178"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_sudo)
|
||||||
|
{
|
||||||
|
const QDir sshDir(QDir::home().absoluteFilePath(".ssh"));
|
||||||
|
|
||||||
|
args.insert(0, "ssh");
|
||||||
|
args.insert(1, "-F");
|
||||||
|
args.insert(2, sshDir.absoluteFilePath("config"));
|
||||||
|
args.insert(3, "-i");
|
||||||
|
args.insert(4, sshDir.absoluteFilePath("id_rsa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::errorOccurred(QProcess::ProcessError error)
|
||||||
|
{
|
||||||
|
qDebug() << m_name << error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::stateChanged(QProcess::ProcessState state)
|
||||||
|
{
|
||||||
|
qDebug() << m_name << state;
|
||||||
|
emit dataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::readyReadStandardOutput()
|
||||||
|
{
|
||||||
|
m_process.setReadChannel(QProcess::StandardOutput);
|
||||||
|
while (m_process.canReadLine())
|
||||||
|
{
|
||||||
|
const auto line = m_process.readLine();
|
||||||
|
//qDebug() << m_name << line;
|
||||||
|
m_logOutput.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entry::readyReadStandardError()
|
||||||
|
{
|
||||||
|
m_process.setReadChannel(QProcess::StandardError);
|
||||||
|
while (m_process.canReadLine())
|
||||||
|
{
|
||||||
|
const auto line = m_process.readLine();
|
||||||
|
//qDebug() << m_name << line;
|
||||||
|
m_logOutput.append(line);
|
||||||
|
}
|
||||||
|
}
|
48
entry.h
Normal file
48
entry.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
class Entry : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Entry(const QString &name, const QString &tunnel, bool sudo, QObject *parent = nullptr);
|
||||||
|
~Entry() override;
|
||||||
|
|
||||||
|
const QString &name() const { return m_name; }
|
||||||
|
const QString &tunnel() const { return m_tunnel; }
|
||||||
|
bool sudo() const { return m_sudo; }
|
||||||
|
|
||||||
|
const QString &logOutput() const { return m_logOutput; }
|
||||||
|
|
||||||
|
Qt::CheckState state() const;
|
||||||
|
|
||||||
|
void toggle();
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
QString binaryName() const;
|
||||||
|
QStringList arguments() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void dataChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void errorOccurred(QProcess::ProcessError error);
|
||||||
|
void stateChanged(QProcess::ProcessState state);
|
||||||
|
void readyReadStandardOutput();
|
||||||
|
void readyReadStandardError();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_name;
|
||||||
|
const QString m_tunnel;
|
||||||
|
const bool m_sudo;
|
||||||
|
|
||||||
|
bool m_readyReceived{false};
|
||||||
|
|
||||||
|
QProcess m_process;
|
||||||
|
|
||||||
|
QString m_logOutput;
|
||||||
|
};
|
25
main.cpp
Normal file
25
main.cpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
qSetMessagePattern(QStringLiteral("%{time dd.MM.yyyy HH:mm:ss.zzz} "
|
||||||
|
"["
|
||||||
|
"%{if-debug}D%{endif}"
|
||||||
|
"%{if-info}I%{endif}"
|
||||||
|
"%{if-warning}W%{endif}"
|
||||||
|
"%{if-critical}C%{endif}"
|
||||||
|
"%{if-fatal}F%{endif}"
|
||||||
|
"] "
|
||||||
|
"%{function}(): "
|
||||||
|
"%{message}"));
|
||||||
|
|
||||||
|
MainWindow mainWindow;
|
||||||
|
mainWindow.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
46
mainwindow.cpp
Normal file
46
mainwindow.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QMainWindow{parent},
|
||||||
|
m_ui{std::make_unique<Ui::MainWindow>()}
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
|
m_ui->treeView->setModel(&m_model);
|
||||||
|
|
||||||
|
connect(m_ui->treeView, &QWidget::customContextMenuRequested, [&view=*m_ui->treeView,&model=m_model](const QPoint &pos){
|
||||||
|
const auto index = view.indexAt(pos);
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto &entry = model.getEntry(index);
|
||||||
|
|
||||||
|
QMenu menu;
|
||||||
|
const auto showLogAction = menu.addAction("Show log");
|
||||||
|
const auto selectedAction = menu.exec(view.viewport()->mapToGlobal(pos));
|
||||||
|
|
||||||
|
if (selectedAction == showLogAction)
|
||||||
|
{
|
||||||
|
QDialog dialog;
|
||||||
|
QVBoxLayout layout;
|
||||||
|
QPlainTextEdit widget;
|
||||||
|
QFont font = widget.document()->defaultFont();
|
||||||
|
font.setFamily("Courier New");
|
||||||
|
widget.document()->setDefaultFont(font);
|
||||||
|
widget.setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||||
|
widget.setReadOnly(true);
|
||||||
|
widget.setPlainText(entry.logOutput());
|
||||||
|
layout.addWidget(&widget);
|
||||||
|
dialog.setLayout(&layout);
|
||||||
|
dialog.exec();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow() = default;
|
23
mainwindow.h
Normal file
23
mainwindow.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
|
#include "vpnmodel.h"
|
||||||
|
|
||||||
|
namespace Ui { class MainWindow; }
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
|
~MainWindow() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::MainWindow> m_ui;
|
||||||
|
|
||||||
|
VpnModel m_model;
|
||||||
|
};
|
63
mainwindow.ui
Normal file
63
mainwindow.ui
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>600</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="startAllButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start all</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="stopAllButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Stop all</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="treeView">
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="rootIsDecorated">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
142
vpnmodel.cpp
Normal file
142
vpnmodel.cpp
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#include "vpnmodel.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
enum {
|
||||||
|
ColumnName,
|
||||||
|
ColumnCommand,
|
||||||
|
NumberOfColumns
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
VpnModel::VpnModel(QObject *parent) :
|
||||||
|
QAbstractTableModel{parent}
|
||||||
|
{
|
||||||
|
for (Entry &entry : m_entries)
|
||||||
|
connect(&entry, &Entry::dataChanged, this, &VpnModel::entryChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VpnModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return std::size(m_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VpnModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return NumberOfColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant VpnModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
const auto &entry = m_entries[index.row()];
|
||||||
|
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case ColumnName:
|
||||||
|
switch (Qt::ItemDataRole(role))
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
return entry.name();
|
||||||
|
case Qt::CheckStateRole:
|
||||||
|
return entry.state();
|
||||||
|
case Qt::FontRole:
|
||||||
|
QFont font;
|
||||||
|
font.setBold(true);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ColumnCommand:
|
||||||
|
switch (Qt::ItemDataRole(role))
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
return entry.binaryName() + ' ' + entry.arguments().join(' ');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant VpnModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (orientation)
|
||||||
|
{
|
||||||
|
case Qt::Horizontal:
|
||||||
|
switch (section)
|
||||||
|
{
|
||||||
|
case ColumnName:
|
||||||
|
switch (Qt::ItemDataRole(role))
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
return tr("Name");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ColumnCommand:
|
||||||
|
switch (Qt::ItemDataRole(role))
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::EditRole:
|
||||||
|
return tr("Command");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VpnModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
auto &entry = m_entries[index.row()];
|
||||||
|
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case ColumnName:
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Qt::CheckStateRole:
|
||||||
|
entry.toggle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags VpnModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
auto flags = QAbstractTableModel::flags(index);
|
||||||
|
if (index.column() == 0)
|
||||||
|
flags |= Qt::ItemIsUserCheckable | Qt::ItemIsAutoTristate;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VpnModel::entryChanged()
|
||||||
|
{
|
||||||
|
const auto *sender_ptr = sender();
|
||||||
|
const auto iter = std::find_if(std::cbegin(m_entries), std::cend(m_entries), [sender_ptr](const Entry &entry){
|
||||||
|
return &entry == sender_ptr;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (iter == std::cend(m_entries))
|
||||||
|
{
|
||||||
|
qCritical() << "unknown sender" << sender_ptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto row = std::distance(std::cbegin(m_entries), iter);
|
||||||
|
|
||||||
|
const auto index = createIndex(row, 0);
|
||||||
|
emit dataChanged(index, index, { Qt::CheckStateRole });
|
||||||
|
}
|
48
vpnmodel.h
Normal file
48
vpnmodel.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "entry.h"
|
||||||
|
|
||||||
|
class VpnModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
VpnModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Entry &getEntry(const QModelIndex &index) { return getEntry(index.row()); }
|
||||||
|
const Entry &getEntry(const QModelIndex &index) const { return getEntry(index.row()); }
|
||||||
|
|
||||||
|
Entry &getEntry(int row) { return m_entries[row]; }
|
||||||
|
const Entry &getEntry(int row) const { return m_entries[row]; }
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent) const override;
|
||||||
|
int columnCount(const QModelIndex &parent) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
|
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void entryChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<Entry, 10> m_entries {
|
||||||
|
Entry { "Bamboo", "-L 127.1.0.1:2233:bamboo.avibit.com:2233", false },
|
||||||
|
Entry { "Bitbucket", "-L 127.2.0.1:2233:bitbucket.avibit.com:2233", false },
|
||||||
|
Entry { "Crucible", "-L 127.3.0.1:2233:crucible.avibit.com:2233", false },
|
||||||
|
Entry { "Confluence", "-L 127.4.0.1:2233:confluence.avibit.com:2233", false },
|
||||||
|
Entry { "Jira", "-L 127.5.0.1:2233:jira.avibit.com:2233", false },
|
||||||
|
|
||||||
|
Entry { "SVN", "-L 3690:svn.avibit.com:3690", false },
|
||||||
|
Entry { "Bitbucket SSH", "-L 127.2.0.1:7999:bitbucket.avibit.com:7999", false },
|
||||||
|
Entry { "Timetool", "-L 8080:timetool.avibit.com:8080", false },
|
||||||
|
//Entry { "Mirror", "-L 80:mirror.avibit.com:80", true },
|
||||||
|
Entry { "Intranet", "-L 80:intranet.avibit.com:80", true },
|
||||||
|
Entry { "Sonarqube", "-L 9000:localhost:9000", false }
|
||||||
|
};
|
||||||
|
};
|
Reference in New Issue
Block a user