Skip to content

Commit eb50892

Browse files
author
ThePBone
committed
Added simplified first launch setup for new users
1 parent 47567c8 commit eb50892

23 files changed

+4954
-243
lines changed

V4L_Frontend.pro

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
#-------------------------------------------------
66

7-
QT += core gui xml network dbus
7+
QT += core gui xml network dbus svg
88
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
99

1010
TARGET = V4L_Frontend
@@ -50,14 +50,17 @@ SOURCES += \
5050
dbus/clientproxy.cpp \
5151
dbus/serveradaptor.cpp \
5252
dialog/androidimporterdlg.cpp \
53+
dialog/animatedvipericon.cpp \
5354
dialog/convolverdlg.cpp \
55+
dialog/firstlaunchwizard.cpp \
5456
dialog/liquidequalizerwidget.cpp \
5557
dialog/logdlg.cpp \
5658
dialog/palettedlg.cpp \
5759
dialog/presetdlg.cpp \
5860
dialog/qanimatedslider.cpp \
5961
dialog/qmessageoverlay.cpp \
6062
dialog/settingsdlg.cpp \
63+
dialog/slidingstackedwidget.cpp \
6164
dialog/statusfragment.cpp \
6265
main.cpp \
6366
mainwindow.cpp \
@@ -97,14 +100,17 @@ HEADERS += \
97100
dbus/clientproxy.h \
98101
dbus/serveradaptor.h \
99102
dialog/androidimporterdlg.h \
103+
dialog/animatedvipericon.h \
100104
dialog/convolverdlg.h \
105+
dialog/firstlaunchwizard.h \
101106
dialog/liquidequalizerwidget.h \
102107
dialog/logdlg.h \
103108
dialog/palettedlg.h \
104109
dialog/presetdlg.h \
105110
dialog/qanimatedslider.h \
106111
dialog/qmessageoverlay.h \
107112
dialog/settingsdlg.h \
113+
dialog/slidingstackedwidget.h \
108114
dialog/statusfragment.h \
109115
mainwindow.h \
110116
misc/autostartmanager.h \
@@ -124,6 +130,7 @@ HEADERS += \
124130

125131
FORMS += \
126132
dialog/convolver.ui \
133+
dialog/firstlaunchwizard.ui \
127134
dialog/importandroid.ui \
128135
dialog/log.ui \
129136
dialog/palettedlg.ui \

config/appconfigwrapper.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ void AppConfigWrapper::setPath(QString npath){
4545
saveAppConfig();
4646
}
4747
QString AppConfigWrapper::getPath(){
48-
QString path = chopFirstLastChar(appconf->getString("io.configpath",true));
48+
QString path = "";
49+
path = appconf->getString("io.configpath",true);
50+
path = chopFirstLastChar(path);
4951
if(path.length() < 2)
5052
return QString("%1/.config/viper4linux/audio.conf").arg(QDir::homePath());
5153
return path;
@@ -128,7 +130,11 @@ void AppConfigWrapper::setTheme(QString thm){
128130
}
129131
QString AppConfigWrapper::getTheme(){
130132
QString name = appconf->getString("theme.name");
131-
if(name.isEmpty()) name = "Fusion";
133+
if(name.isEmpty()){
134+
name = "Fusion";
135+
appconf->setValue("theme.name",name);
136+
emit styleChanged();
137+
}
132138
return name;
133139
}
134140
QString AppConfigWrapper::getIrsPath(){
@@ -227,6 +233,13 @@ void AppConfigWrapper::setEqualizerPermanentHandles(bool b){
227233
bool AppConfigWrapper::getEqualizerPermanentHandles(){
228234
return appconf->getBool("equalizer.handle.permanent");
229235
}
236+
void AppConfigWrapper::setIntroShown(bool b){
237+
appconf->setValue("app.firstlaunch",QVariant(b));
238+
saveAppConfig();
239+
}
240+
bool AppConfigWrapper::getIntroShown(){
241+
return appconf->getBool("app.firstlaunch");
242+
}
230243
//--------
231244
QString AppConfigWrapper::getAppConfigFilePath(){
232245
return QString("%1/.config/viper4linux/ui.2.conf").arg(QDir::homePath());

config/appconfigwrapper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class AppConfigWrapper : public QObject
8686
void setSpectrumMultiplier(float number);
8787
void setEqualizerPermanentHandles(bool b);
8888
bool getEqualizerPermanentHandles();
89+
void setIntroShown(bool b);
90+
bool getIntroShown();
8991
signals:
9092
void spectrumChanged();
9193
void spectrumReloadRequired();

dialog/animatedvipericon.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "animatedvipericon.h"
2+
3+
AnimatedViperIcon::AnimatedViperIcon(QWidget *parent)
4+
: QWidget(parent)
5+
{
6+
svgItem->setGeometry(0,0,64,64);
7+
svgItemU->setGeometry(0,0,64,64);
8+
svgItemL->setGeometry(0,0,64,64);
9+
this->setGeometry(0,0,64,64);
10+
this->setFixedSize(64,64);
11+
12+
svgItemU->hide();
13+
svgItemL->hide();
14+
15+
group = new QParallelAnimationGroup(this);
16+
QPropertyAnimation *upper = new QPropertyAnimation(svgItemU, "geometry");
17+
upper->setDuration(1000);
18+
upper->setEasingCurve(QEasingCurve::Type::OutExpo);
19+
upper->setStartValue(QRect(0, -64, 64, 64));
20+
upper->setEndValue(QRect(0, 0, 64, 64));
21+
group->addAnimation(upper);
22+
QPropertyAnimation *lower = new QPropertyAnimation(svgItemL, "geometry");
23+
lower->setDuration(1000);
24+
lower->setEasingCurve(QEasingCurve::Type::OutExpo);
25+
lower->setStartValue(QRect(0, 128, 64, 64));
26+
lower->setEndValue(QRect(0, 0, 64, 64));
27+
group->addAnimation(lower);
28+
}
29+
30+
AnimatedViperIcon::~AnimatedViperIcon()
31+
{
32+
delete svgItem;
33+
delete svgItemU;
34+
delete svgItemL;
35+
}
36+
37+
void AnimatedViperIcon::startAnimation()
38+
{
39+
if(group->state() == QAbstractAnimation::Running)
40+
group->stop();
41+
group->start();
42+
svgItemU->show();
43+
svgItemL->show();
44+
}
45+

dialog/animatedvipericon.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef WIDGET_H
2+
#define WIDGET_H
3+
4+
#include <QPropertyAnimation>
5+
#include <QSvgWidget>
6+
#include <QParallelAnimationGroup>
7+
8+
class AnimatedViperIcon : public QWidget
9+
{
10+
Q_OBJECT
11+
12+
public:
13+
AnimatedViperIcon(QWidget *parent = nullptr);
14+
~AnimatedViperIcon();
15+
void startAnimation();
16+
private:
17+
QSvgWidget* svgItem = new QSvgWidget(":/icons/parts/viper.svg",this);
18+
QSvgWidget* svgItemU = new QSvgWidget(":/icons/parts/upper.svg",this);
19+
QSvgWidget* svgItemL = new QSvgWidget(":/icons/parts/lower.svg",this);
20+
QParallelAnimationGroup *group;
21+
};
22+
#endif // WIDGET_H

dialog/firstlaunchwizard.cpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#include "firstlaunchwizard.h"
2+
#include "ui_firstlaunchwizard.h"
3+
#include "misc/common.h"
4+
#include "misc/autostartmanager.h"
5+
#include "mainwindow.h"
6+
7+
#include <QTimer>
8+
#include <QEasingCurve>
9+
#include <QDesktopServices>
10+
#include <QUrl>
11+
#include <QFileInfo>
12+
#include <QDir>
13+
#include <QProcess>
14+
15+
FirstLaunchWizard::FirstLaunchWizard(AppConfigWrapper* _appconf, MainWindow* mainwin, QWidget *parent) :
16+
QWidget(parent),
17+
ui(new Ui::FirstLaunchWizard)
18+
{
19+
ui->setupUi(this);
20+
21+
appconf = _appconf;
22+
23+
QTimer::singleShot(1000, [&]{
24+
ui->p1_icon->startAnimation();
25+
});
26+
ui->p2_icon->startAnimation();
27+
ui->p3_icon->startAnimation();
28+
ui->p4_icon->startAnimation();
29+
30+
31+
ui->stackedWidget->setAnimation(QEasingCurve::Type::OutCirc);
32+
connect(ui->p1_next,&QPushButton::clicked,[&]{
33+
ui->stackedWidget->slideInIdx(1);
34+
});
35+
connect(ui->p2_next,&QPushButton::clicked,[&]{
36+
ui->stackedWidget->slideInIdx(2);
37+
});
38+
connect(ui->p3_next,&QPushButton::clicked,[&]{
39+
ui->stackedWidget->slideInIdx(3);
40+
});
41+
connect(ui->p4_next,&QPushButton::clicked,[&]{
42+
emit wizardFinished();
43+
});
44+
connect(ui->p4_telegram,&QPushButton::clicked,[&]{
45+
QDesktopServices::openUrl(QUrl("https://t.me/joinchat/FTKC2A2bolHkFAyO-fuPjw"));
46+
});
47+
48+
auto deviceUpdated = [this](){
49+
if(lockslot) return;
50+
QString absolute =
51+
QFileInfo(appconf->getPath()).absoluteDir().absolutePath();
52+
QString devices(pathAppend(absolute,"devices.conf"));
53+
if(ui->p2_dev_mode_auto->isChecked()){
54+
QFile(devices).remove();
55+
}else{
56+
if(ui->p2_dev_select->currentData() == "---")
57+
return;
58+
59+
ConfigContainer* devconf = new ConfigContainer();
60+
devconf->setConfigMap(ConfigIO::readFile(devices));
61+
devconf->setValue("location",ui->p2_dev_select->currentData());
62+
ConfigIO::writeFile(devices,devconf->getConfigMap());
63+
}
64+
};
65+
refreshDevices();
66+
67+
68+
ui->p3_systray_disable->setChecked(!appconf->getTrayMode());
69+
ui->p3_systray_enable->setChecked(appconf->getTrayMode());
70+
ui->p3_systray_icon_box->setEnabled(appconf->getTrayMode());
71+
72+
QString autostart_path = AutostartManager::getAutostartPath("viper-gui.desktop");
73+
bool autostart_enabled = AutostartManager::inspectDesktopFile(autostart_path,AutostartManager::Exists);
74+
bool autostartviper_enabled = AutostartManager::inspectDesktopFile(autostart_path,AutostartManager::UsesViperAutostart);
75+
76+
ui->p3_systray_minOnBoot->setChecked(autostart_enabled);
77+
ui->p3_systray_autostartViper->setEnabled(autostart_enabled);
78+
ui->p3_systray_autostartViper->setChecked(autostartviper_enabled);
79+
80+
auto systray_radio = [this,mainwin]{
81+
if(lockslot)return;
82+
int mode = 0;
83+
if(ui->p3_systray_disable->isChecked())mode=0;
84+
else if(ui->p3_systray_enable->isChecked())mode=1;
85+
appconf->setTrayMode(mode);
86+
mainwin->setTrayVisible(mode);
87+
ui->p3_systray_icon_box->setEnabled(mode);
88+
};
89+
90+
connect(ui->p3_systray_disable,&QRadioButton::clicked,this,systray_radio);
91+
connect(ui->p3_systray_enable,&QRadioButton::clicked,this,systray_radio);
92+
93+
auto systray_autostart_radio = [this,autostart_path,mainwin]{
94+
if(ui->p3_systray_minOnBoot->isChecked()){
95+
AutostartManager::saveDesktopFile(autostart_path,mainwin->GetExecutablePath(),
96+
ui->p3_systray_autostartViper->isChecked());
97+
}
98+
else QFile(autostart_path).remove();
99+
ui->p3_systray_autostartViper->setEnabled(ui->p3_systray_minOnBoot->isChecked());
100+
};
101+
102+
connect(ui->p3_systray_minOnBoot,&QPushButton::clicked,this,systray_autostart_radio);
103+
connect(ui->p3_systray_autostartViper,&QPushButton::clicked,this,systray_autostart_radio);
104+
105+
connect(ui->p2_dev_mode_auto,&QRadioButton::clicked,this,deviceUpdated);
106+
connect(ui->p2_dev_mode_manual,&QRadioButton::clicked,this,deviceUpdated);
107+
connect(ui->p2_dev_select,static_cast<void (QComboBox::*)(const QString&)>(&QComboBox::currentIndexChanged), this, deviceUpdated);
108+
109+
}
110+
111+
FirstLaunchWizard::~FirstLaunchWizard()
112+
{
113+
delete ui;
114+
}
115+
116+
void FirstLaunchWizard::refreshDevices()
117+
{
118+
lockslot = true;
119+
ui->p2_dev_select->clear();
120+
QString absolute =
121+
QFileInfo(appconf->getPath()).absoluteDir().absolutePath();
122+
QFile devices(pathAppend(absolute,"devices.conf"));
123+
bool devmode_auto = !devices.exists();
124+
ui->p2_dev_mode_auto->setChecked(devmode_auto);
125+
ui->p2_dev_mode_manual->setChecked(!devmode_auto);
126+
127+
QProcess process;
128+
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
129+
env.insert("LC_ALL", "C");
130+
process.setProcessEnvironment(env);
131+
process.start("sh", QStringList()<<"-c"<<"pactl list sinks | grep \'Name: \' -A1");
132+
process.waitForFinished(500);
133+
134+
ConfigContainer* devconf = new ConfigContainer();
135+
devconf->setConfigMap(ConfigIO::readFile(pathAppend(absolute,"devices.conf")));
136+
QString out = process.readAllStandardOutput();
137+
ui->p2_dev_select->addItem("...","---");
138+
for(auto item : out.split("Name:")){
139+
item.prepend("Name:");
140+
QRegularExpression re("(?<=(Name:)\\s)(?<name>.+)[\\s\\S]+(?<=(Description:)\\s)(?<desc>.+)");
141+
QRegularExpressionMatch match = re.match(item, 0, QRegularExpression::PartialPreferCompleteMatch);
142+
if(match.hasMatch()){
143+
ui->p2_dev_select->addItem(QString("%1 (%2)").arg(match.captured("desc")).arg(match.captured("name")),
144+
match.captured("name"));
145+
}
146+
}
147+
QString dev_location = devconf->getString("location");
148+
if(dev_location.isEmpty())
149+
ui->p2_dev_select->setCurrentIndex(0);
150+
else{
151+
bool notFound = true;
152+
for(int i = 0; i < ui->p2_dev_select->count(); i++){
153+
if(ui->p2_dev_select->itemData(i) ==
154+
dev_location){
155+
notFound = false;
156+
ui->p2_dev_select->setCurrentIndex(i);
157+
break;
158+
}
159+
}
160+
if(notFound){
161+
QString name = QString("Unknown (%1)").arg(dev_location);
162+
ui->p2_dev_select->addItem(name,dev_location);
163+
ui->p2_dev_select->setCurrentText(name);
164+
}
165+
}
166+
lockslot = false;
167+
}

dialog/firstlaunchwizard.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef FIRSTLAUNCHWIZARD_H
2+
#define FIRSTLAUNCHWIZARD_H
3+
4+
#include <QWidget>
5+
#include "config/appconfigwrapper.h"
6+
7+
class MainWindow;
8+
9+
namespace Ui {
10+
class FirstLaunchWizard;
11+
}
12+
13+
class FirstLaunchWizard : public QWidget
14+
{
15+
Q_OBJECT
16+
17+
public:
18+
explicit FirstLaunchWizard(AppConfigWrapper* _appconf, MainWindow*,QWidget *parent = nullptr);
19+
~FirstLaunchWizard();
20+
21+
signals:
22+
void wizardFinished();
23+
24+
private:
25+
Ui::FirstLaunchWizard *ui;
26+
AppConfigWrapper* appconf;
27+
bool lockslot = false;
28+
29+
void refreshDevices();
30+
};
31+
32+
#endif // FIRSTLAUNCHWIZARD_H

0 commit comments

Comments
 (0)