Install dialog in UI.

This commit is contained in:
Adam Ierymenko 2014-01-03 22:14:30 -08:00
parent 029f64495c
commit 67a71868cb
7 changed files with 384 additions and 19 deletions

View File

@ -39,7 +39,8 @@ SOURCES += main.cpp\
../node/Utils.cpp \
../ext/lz4/lz4.c \
../ext/lz4/lz4hc.c \
networkwidget.cpp
networkwidget.cpp \
installdialog.cpp
HEADERS += mainwindow.h \
aboutwindow.h \
@ -88,11 +89,13 @@ HEADERS += mainwindow.h \
../node/UdpSocket.hpp \
../ext/lz4/lz4.h \
../ext/lz4/lz4hc.h \
networkwidget.h
networkwidget.h \
installdialog.h
FORMS += mainwindow.ui \
aboutwindow.ui \
networkwidget.ui
networkwidget.ui \
installdialog.ui
RESOURCES += \
resources.qrc

View File

@ -0,0 +1,83 @@
#include "installdialog.h"
#include "mainwindow.h"
#include "ui_installdialog.h"
#include "../node/Defaults.hpp"
#include <QMainWindow>
#include <QMessageBox>
#include <QByteArray>
#include <QSslSocket>
InstallDialog::InstallDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::InstallDialog),
nam(new QNetworkAccessManager(this))
{
ui->setupUi(this);
QObject::connect(nam,SIGNAL(finished(QNetworkReply*)),this,SLOT(on_networkReply(QNetworkReply*)));
const char *nfoUrl = ZeroTier::ZT_DEFAULTS.updateLatestNfoURL.c_str();
if (!*nfoUrl) {
QMessageBox::critical(this,"Download Failed","Download failed: internal error: no update URL configured in build!",QMessageBox::Ok,QMessageBox::NoButton);
QApplication::exit(1);
return;
}
QNetworkReply *reply = nam->get(QNetworkRequest(QUrl(nfoUrl)));
QObject::connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(on_downloadProgress(qint64,qint64)));
}
InstallDialog::~InstallDialog()
{
delete ui;
}
void InstallDialog::on_networkReply(QNetworkReply *reply)
{
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
QMessageBox::critical(this,"Download Failed",QString("Download failed: ") + reply->errorString(),QMessageBox::Ok,QMessageBox::NoButton);
QApplication::exit(1);
return;
} else {
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) {
QByteArray installerData(reply->readAll());
installerData.append((char)0);
printf("%s\n",installerData.data());
} else {
QMessageBox::critical(this,"Download Failed",QString("Download failed: HTTP status code ") + reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString(),QMessageBox::Ok,QMessageBox::NoButton);
QApplication::exit(1);
return;
}
}
}
void InstallDialog::on_InstallDialog_rejected()
{
QApplication::exit();
}
//((QMainWindow *)this->parent())->setHidden(false);
void InstallDialog::on_cancelButton_clicked()
{
QApplication::exit();
}
void InstallDialog::on_downloadProgress(qint64 bytesReceived,qint64 bytesTotal)
{
if (bytesTotal <= 0) {
ui->progressBar->setValue(0);
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(0);
} else {
double pct = ((double)bytesReceived / (double)bytesTotal) * 100.0;
if (pct > 100.0)
pct = 100.0;
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(100);
ui->progressBar->setValue((int)pct);
}
}

View File

@ -0,0 +1,33 @@
#ifndef INSTALLDIALOG_H
#define INSTALLDIALOG_H
#include <QDialog>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
namespace Ui {
class InstallDialog;
}
class InstallDialog : public QDialog
{
Q_OBJECT
public:
explicit InstallDialog(QWidget *parent = 0);
~InstallDialog();
private slots:
void on_networkReply(QNetworkReply *reply);
void on_InstallDialog_rejected();
void on_cancelButton_clicked();
void on_downloadProgress(qint64 bytesReceived,qint64 bytesTotal);
private:
Ui::InstallDialog *ui;
QNetworkAccessManager *nam;
};
#endif // INSTALLDIALOG_H

131
ZeroTierUI/installdialog.ui Normal file
View File

@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>InstallDialog</class>
<widget class="QDialog" name="InstallDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>231</height>
</rect>
</property>
<property name="windowTitle">
<string>Install ZeroTier One Service</string>
</property>
<property name="windowIcon">
<iconset resource="resources.qrc">
<normaloff>:/img/zt1icon.png</normaloff>:/img/zt1icon.png</iconset>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string>Since this is your first time running ZeroTier One on this computer, the virtual Ethernet service must be downloaded and installed.
Please wait while the service downloads, then you will be prompted to enter an administrator password to install it.</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>10</number>
</property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<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>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel and Exit</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -2,6 +2,7 @@
#include "aboutwindow.h"
#include "networkwidget.h"
#include "ui_mainwindow.h"
#include "installdialog.h"
#include <string>
#include <map>
@ -54,16 +55,14 @@ static void handleZTMessage(void *arg,unsigned long id,const char *line)
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
nam(new QNetworkAccessManager(this))
pollServiceTimerId(0)
{
ui->setupUi(this);
this->startTimer(1000); // poll service every second
this->pollServiceTimerId = this->startTimer(1000);
this->setEnabled(false); // gets enabled when updates are received
mainWindow = this;
this->cyclesSinceResponseFromService = 0;
QObject::connect(nam,SIGNAL(finished(QNetworkReply*)),this,SLOT(on_networkReply(QNetworkReply*)));
if (ui->networkListWidget->verticalScrollBar())
ui->networkListWidget->verticalScrollBar()->setSingleStep(8);
@ -84,11 +83,15 @@ void MainWindow::timerEvent(QTimerEvent *event)
{
event->accept();
if (this->isHidden())
return;
if (!zeroTierClient) {
std::string authToken;
if (!ZeroTier::Utils::readFile(ZeroTier::Node::LocalClient::authTokenDefaultUserPath().c_str(),authToken)) {
#ifdef __APPLE__
if (QFile::exists("/Library/Application Support/ZeroTier/One/zerotier-one")) {
//if (QFile::exists("/Library/Application Support/ZeroTier/One/zerotier-one")) {
if (false) {
// Run the little AppleScript hack that asks for admin credentials and
// then installs the auth token file in the current user's home.
QString authHelperPath(QCoreApplication::applicationDirPath() + "/../Resources/helpers/mac/ZeroTier One (Authenticate).app/Contents/MacOS/applet");
@ -105,11 +108,18 @@ void MainWindow::timerEvent(QTimerEvent *event)
}
QProcess::execute(authHelperPath,QStringList());
} else {
// Download the latest version and install it
// If the service is not installed, download the installer and run it
// for the first time.
this->setEnabled(false);
InstallDialog *id = new InstallDialog(this);
id->setModal(true);
id->show();
this->setHidden(true);
return;
// Run the little AppleScript hack that asks for admin credentials and
// then installs the auth token file in the current user's home.
/*
QString installHelperPath(QCoreApplication::applicationDirPath() + "/../Resources/helpers/mac/ZeroTier One (Install).app/Contents/MacOS/applet");
if (!QFile::exists(installHelperPath)) {
QMessageBox::critical(this,"Unable to Locate Helper","Unable to locate install helper, cannot install service.",QMessageBox::Ok,QMessageBox::NoButton);
@ -117,6 +127,7 @@ void MainWindow::timerEvent(QTimerEvent *event)
return;
}
QProcess::execute(installHelperPath,QStringList());
*/
}
#endif
@ -306,7 +317,3 @@ void MainWindow::on_addressButton_clicked()
{
QApplication::clipboard()->setText(this->myAddress);
}
void MainWindow::on_networkReply(QNetworkReply *reply)
{
}

View File

@ -4,10 +4,6 @@
#include <QMainWindow>
#include <QEvent>
#include <QString>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <map>
#include <vector>
@ -55,15 +51,14 @@ private slots:
void on_actionAbout_triggered();
void on_networkIdLineEdit_textChanged(const QString &text);
void on_addressButton_clicked();
void on_networkReply(QNetworkReply *reply);
private:
Ui::MainWindow *ui;
QNetworkAccessManager *nam;
QString myAddress;
QString myStatus;
QString myVersion;
int pollServiceTimerId;
unsigned int numPeers;
unsigned int cyclesSinceResponseFromService;
std::map< std::string,std::vector<std::string> > networks;

View File

@ -0,0 +1,113 @@
#!/bin/bash
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
shopt -s expand_aliases
dryRun=0
echo "*** ZeroTier One install/update ***"
if [ "$UID" -ne 0 ]; then
echo "Not running as root so doing dry run (no modifications to system)..."
dryRun=1
fi
if [ $dryRun -gt 0 ]; then
alias ln="echo '>> dry run: ln'"
alias rm="echo '>> dry run: rm'"
alias mv="echo '>> dry run: mv'"
alias chown="echo '>> dry run: chown'"
alias chgrp="echo '>> dry run: chgrp'"
alias launchctl="echo '>> dry run: launchctl'"
alias zerotier-cli="echo '>> dry run: zerotier-cli'"
fi
zthome="/Library/Application Support/ZeroTier/One"
ztapp=`mdfind kMDItemCFBundleIdentifier == 'com.zerotier.ZeroTierOne'`
if [ ! -d "$ztapp" ]; then
ztapp="/Applications/ZeroTier One.app"
fi
scriptPath="`dirname "$0"`/`basename "$0"`"
if [ ! -r "$scriptPath" ]; then
scriptPath="$0"
if [ ! -r "$scriptPath" ]; then
echo "Installer cannot determine its own path; $scriptPath is not readable."
exit 2
fi
fi
endMarkerIndex=`grep -a -b -E '^################' "$scriptPath" | head -c 16 | cut -d : -f 1`
if [ "$endMarkerIndex" -le 100 ]; then
echo 'Internal error: unable to find end of script / start of binary data marker.'
exit 2
fi
blobStart=`expr $endMarkerIndex + 17`
if [ "$blobStart" -le "$endMarkerIndex" ]; then
echo 'Internal error: unable to find end of script / start of binary data marker.'
exit 2
fi
echo 'Extracting files...'
if [ $dryRun -gt 0 ]; then
echo ">> dry run: tail -c +$blobStart \"$scriptPath\" | bunzip2 -c | tar -xvop -C / -f -"
else
tail -c +$blobStart "$scriptPath" | bunzip2 -c | tar -xvop -C / -f -
fi
if [ $dryRun -eq 0 -a ! -d "/Applications/ZeroTier One_app.LATEST" ]; then
echo 'Archive extraction failed, cannot find zerotier-one binary.'
exit 2
fi
echo 'Installing/updating ZeroTier One.app...'
if [ -d "$ztapp" ]; then
# Preserve ownership of existing .app and install new version in the
# same location.
currentAppOwner=`stat -f '%u' "$ztapp"`
currentAppGroup=`stat -f '%g' "$ztapp"`
if [ ! -z "$currentAppOwner" -a ! -z "$currentAppGroup" ]; then
rm -rf "$ztapp"
mv -f "/Application/ZeroTier One_app.LATEST" "$ztapp"
chown -R $currentAppOwner "$ztapp"
chgrp -R $currentAppGroup "$ztapp"
else
rm -rf "$ztapp"
mv -f "/Application/ZeroTier One_app.LATEST" "$ztapp"
fi
else
# If there is no existing app, just drop the shipped one into place
mv -f "/Applications/ZeroTier One_app.LATEST" "/Applications/ZeroTier One.app"
fi
echo 'Installing zerotier-cli command line utility...'
ln -sf "/Library/Application Support/ZeroTier/One/zerotier-one" /usr/bin/zerotier-cli
if [ ! -f '/Library/Application Support/ZeroTier/One/authtoken.secret' ]; then
echo 'Pre-creating authtoken.secret for ZeroTier service...'
if [ $dryRun -eq 0 ]; then
rm -f '/Library/Application Support/ZeroTier/One/authtoken.secret'
head -c 1024 /dev/urandom | md5 | head -c 24 >'/Library/Application Support/ZeroTier/One/authtoken.secret'
chmod 0600 '/Library/Application Support/ZeroTier/One/authtoken.secret'
fi
fi
echo 'Installing and (re-)starting zerotier-one service via launchctl...'
if [ ! -z "`launchctl list | grep -F com.zerotier.one`" ]; then
launchctl unload /Library/LaunchDaemons/com.zerotier.one.plist
fi
launchctl load /Library/LaunchDaemons/com.zerotier.one.plist
sleep 1
zerotier-cli info
exit 0
# Do not remove the last line or add a carriage return to it! The installer
# looks for an unterminated line beginning with 16 #'s in itself to find
# the binary blob data, which is appended after it.
################