Imported existing sources
This commit is contained in:
103
.gitignore
vendored
103
.gitignore
vendored
@@ -1,52 +1,73 @@
|
||||
# C++ objects and libs
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.la
|
||||
*.lai
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*.dll
|
||||
*.dylib
|
||||
|
||||
# Qt-es
|
||||
object_script.*.Release
|
||||
object_script.*.Debug
|
||||
*_plugin_import.cpp
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.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
|
||||
target_wrapper.*
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# QtCreator
|
||||
*.autosave
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# QtCreator Qml
|
||||
*.qmlproject.user
|
||||
*.qmlproject.user.*
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# QtCreator CMake
|
||||
CMakeLists.txt.user*
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# QtCreator 4.8< compilation database
|
||||
compile_commands.json
|
||||
# MinGW generated files
|
||||
*.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