1 /*
2 Copyright (c) 2012-2020 Maarten Baert <maarten-baert@hotmail.com>
3 
4 This file is part of SimpleScreenRecorder.
5 
6 SimpleScreenRecorder is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 SimpleScreenRecorder is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with SimpleScreenRecorder.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "ProfileBox.h"
21 
22 #include "Logger.h"
23 #include "CommandLineOptions.h"
24 #include "Dialogs.h"
25 #include "MainWindow.h"
26 
ProfileBox(const QString & title,QWidget * parent,const QString & type,LoadCallback load_callback,SaveCallback save_callback,void * userdata)27 ProfileBox::ProfileBox(const QString& title, QWidget* parent, const QString& type, LoadCallback load_callback, SaveCallback save_callback, void *userdata)
28 	: QGroupBox(title, parent) {
29 
30 	m_type = type;
31 	m_load_callback = load_callback;
32 	m_save_callback = save_callback;
33 	m_userdata = userdata;
34 
35 	m_combobox_profiles = new QComboBox(this);
36 	m_combobox_profiles->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
37 	m_pushbutton_save = new QPushButton(tr("Save"), this);
38 	m_pushbutton_save->setToolTip(tr("Save the current settings to this profile."));
39 	m_pushbutton_new = new QPushButton(tr("New"), this);
40 	m_pushbutton_new->setToolTip(tr("Create a new profile with the current settings."));
41 	m_pushbutton_delete = new QPushButton(tr("Delete"), this);
42 	m_pushbutton_delete->setToolTip(tr("Delete this profile."));
43 
44 	connect(m_combobox_profiles, SIGNAL(activated(int)), this, SLOT(OnProfileChange()));
45 	connect(m_pushbutton_save, SIGNAL(clicked()), this, SLOT(OnProfileSave()));
46 	connect(m_pushbutton_new, SIGNAL(clicked()), this, SLOT(OnProfileNew()));
47 	connect(m_pushbutton_delete, SIGNAL(clicked()), this, SLOT(OnProfileDelete()));
48 
49 	QHBoxLayout *layout = new QHBoxLayout(this);
50 	layout->addWidget(m_combobox_profiles);
51 	layout->addWidget(m_pushbutton_save);
52 	layout->addWidget(m_pushbutton_new);
53 	layout->addWidget(m_pushbutton_delete);
54 
55 	LoadProfiles();
56 	UpdateProfileFields();
57 
58 }
59 
GetProfileName()60 QString ProfileBox::GetProfileName() {
61 	unsigned int profile = GetProfile();
62 	if(profile == 0)
63 		return QString();
64 	return m_profiles[profile - 1].m_name;
65 }
66 
FindProfile(const QString & name)67 unsigned int ProfileBox::FindProfile(const QString& name) {
68 	for(unsigned int i = 0; i < m_profiles.size(); ++i) {
69 		if(m_profiles[i].m_name == name)
70 			return i + 1;
71 	}
72 	return 0;
73 }
74 
LoadProfiles()75 void ProfileBox::LoadProfiles() {
76 
77 	// get all profiles
78 	std::vector<Profile> profiles;
79 	LoadProfilesFromDir(&profiles, GetApplicationSystemDir(m_type), false);
80 	LoadProfilesFromDir(&profiles, GetApplicationUserDir(m_type), true);
81 
82 	// sort and remove duplicates
83 	std::sort(profiles.begin(), profiles.end());
84 	m_profiles.clear();
85 	for(const Profile& p : profiles) {
86 		if(!m_profiles.empty() && m_profiles.back().m_name == p.m_name) {
87 			if(p.m_can_delete)
88 				m_profiles.back().m_can_delete = true;
89 		} else {
90 			m_profiles.push_back(p);
91 		}
92 	}
93 
94 	// add profiles to combobox
95 	m_combobox_profiles->clear();
96 	m_combobox_profiles->addItem("\u200e" + tr("(none)") + "\u200e");
97 	for(unsigned int i = 0; i < m_profiles.size(); ++i) {
98 		m_combobox_profiles->addItem("\u200e" + QByteArray::fromPercentEncoding(m_profiles[i].m_name.toUtf8()) + "\u200e");
99 	}
100 
101 }
102 
LoadProfilesFromDir(std::vector<Profile> * profiles,const QString & path,bool can_delete)103 void ProfileBox::LoadProfilesFromDir(std::vector<Profile>* profiles, const QString& path, bool can_delete) {
104 	QDir dir(path);
105 	dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
106 	dir.setNameFilters(QStringList("*.conf"));
107 	for(QFileInfo file : dir.entryInfoList()) {
108 		Profile profile;
109 		profile.m_name = file.completeBaseName();
110 		profile.m_can_delete = can_delete;
111 		profiles->push_back(profile);
112 	}
113 }
114 
UpdateProfileFields()115 void ProfileBox::UpdateProfileFields() {
116 	unsigned int profile = GetProfile();
117 	m_pushbutton_save->setEnabled(profile != 0);
118 	m_pushbutton_new->setEnabled(true);
119 	m_pushbutton_delete->setEnabled(profile != 0 && m_profiles[profile - 1].m_can_delete);
120 }
121 
OnProfileChange()122 void ProfileBox::OnProfileChange() {
123 	UpdateProfileFields();
124 	QString name = GetProfileName();
125 	if(name.isEmpty())
126 		return;
127 	QString filename = GetApplicationUserDir(m_type) + "/" + name + ".conf";
128 	if(QFileInfo(filename).exists()) {
129 		QSettings settings(filename, QSettings::IniFormat);
130 		m_load_callback(&settings, m_userdata);
131 		return;
132 	}
133 	filename = GetApplicationSystemDir(m_type) + "/" + name + ".conf";
134 	if(QFileInfo(filename).exists()) {
135 		QSettings settings(filename, QSettings::IniFormat);
136 		m_load_callback(&settings, m_userdata);
137 		return;
138 	}
139 	Logger::LogError("[ProfileBox::OnProfileChange] " + tr("Error: Can't load profile!"));
140 }
141 
OnProfileSave()142 void ProfileBox::OnProfileSave() {
143 	QString name = GetProfileName();
144 	if(name.isEmpty())
145 		return;
146 	QString filename = GetApplicationUserDir(m_type) + "/" + name + ".conf";
147 	if(MessageBox(QMessageBox::Warning, this, MainWindow::WINDOW_CAPTION, tr("Are you sure that you want to overwrite this profile?"), BUTTON_YES | BUTTON_NO, BUTTON_YES) == BUTTON_YES) {
148 		{
149 			QSettings settings(filename, QSettings::IniFormat);
150 			m_save_callback(&settings, m_userdata);
151 		}
152 		LoadProfiles();
153 		SetProfile(FindProfile(name));
154 		UpdateProfileFields();
155 	}
156 }
157 
OnProfileNew()158 void ProfileBox::OnProfileNew() {
159 	QString name = InputBox(this, MainWindow::WINDOW_CAPTION, tr("Enter a name for the new profile:"), "");
160 	if(name.isEmpty())
161 		return;
162 	name = name.toUtf8().toPercentEncoding(); // TODO: exclude the following characters: " !#$%&'()+,;=@[]^{}"
163 	QString filename = GetApplicationUserDir(m_type) + "/" + name + ".conf";
164 	if(!QFileInfo(filename).exists() || MessageBox(QMessageBox::Warning, this, MainWindow::WINDOW_CAPTION,
165 			tr("A profile with the same name already exists. Are you sure that you want to replace it?"), BUTTON_YES | BUTTON_NO, BUTTON_YES) == BUTTON_YES) {
166 		{
167 			QSettings settings(filename, QSettings::IniFormat);
168 			m_save_callback(&settings, m_userdata);
169 		}
170 		LoadProfiles();
171 		SetProfile(FindProfile(name));
172 		UpdateProfileFields();
173 	}
174 }
175 
OnProfileDelete()176 void ProfileBox::OnProfileDelete() {
177 	QString name = GetProfileName();
178 	if(name.isEmpty())
179 		return;
180 	QString filename = GetApplicationUserDir(m_type) + "/" + name + ".conf";
181 	if(MessageBox(QMessageBox::Warning, this, MainWindow::WINDOW_CAPTION, tr("Are you sure that you want to delete this profile?"), BUTTON_YES | BUTTON_NO, BUTTON_YES) == BUTTON_YES) {
182 		QFile(filename).remove();
183 		LoadProfiles();
184 		UpdateProfileFields();
185 	}
186 }
187