blob: f3105943474de09332eb7d4c1cb98f87d44563df [file] [log] [blame]
Jared Lindblom06405c42013-01-17 20:48:39 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012-2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Jared Lindblom <lindblom@cs.ucla.edu>
19 */
20
21#include "chronosharegui.h"
Alexander Afanasyev83a53002013-01-24 11:12:01 -080022#include "logging.h"
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080023#include "ccnx-wrapper.h"
24
25#include <boost/make_shared.hpp>
26
27using namespace boost;
28using namespace Ccnx;
Jared Lindblom06405c42013-01-17 20:48:39 -080029
Alexander Afanasyev83a53002013-01-24 11:12:01 -080030INIT_LOGGER ("Gui");
31
32ChronoShareGui::ChronoShareGui(QWidget *parent)
Jared Lindblomc8ffd592013-01-25 00:00:30 -080033 : QDialog(parent)
Jared Lindblom06405c42013-01-17 20:48:39 -080034{
Jared Lindblomc8ffd592013-01-25 00:00:30 -080035
36 setWindowTitle("Preferences");
37
38 labelUsername = new QLabel("Username");
39 labelSharedFolder = new QLabel("Shared Folder Name");
40 labelSharedFolderPath = new QLabel("Shared Folder Path");
41 editUsername = new QLineEdit();
42 editSharedFolder = new QLineEdit();
43 editSharedFolderPath = new QLineEdit();
44 editSharedFolderPath->setReadOnly(true);
45 QPalette pal = editSharedFolderPath->palette();
46 pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Disabled, QPalette::Base));
47 editSharedFolderPath->setPalette(pal);
48 button = new QPushButton("Submit");
49 label = new QLabel();
50
51 connect(button, SIGNAL(clicked()), this, SLOT(changeSettings()));
52
53 mainLayout = new QVBoxLayout; //vertically
54 mainLayout->addWidget(labelUsername);
55 mainLayout->addWidget(editUsername);
56 mainLayout->addWidget(labelSharedFolder);
57 mainLayout->addWidget(editSharedFolder);
58 mainLayout->addWidget(labelSharedFolderPath);
59 mainLayout->addWidget(editSharedFolderPath);
60 mainLayout->addWidget(button);
61 mainLayout->addWidget(label);
62 setLayout(mainLayout);
63
Alexander Afanasyev83a53002013-01-24 11:12:01 -080064 // load settings
65 if(!loadSettings())
Jared Lindblom5d7e51e2013-01-18 00:59:34 -080066 {
Alexander Afanasyev83a53002013-01-24 11:12:01 -080067 // prompt user to choose folder
Jared Lindblomc8ffd592013-01-25 00:00:30 -080068 openMessageBox("First Time Setup", "Please enter a username, shared folder name and choose the shared folder path on your local filesystem.");
69 viewSettings();
Alexander Afanasyev83a53002013-01-24 11:12:01 -080070 openFileDialog();
Jared Lindblomc8ffd592013-01-25 00:00:30 -080071 viewSettings();
Jared Lindblom5d7e51e2013-01-18 00:59:34 -080072 }
Jared Lindblomb4032e22013-01-17 23:50:51 -080073
Alexander Afanasyev83a53002013-01-24 11:12:01 -080074 // create actions that result from clicking a menu option
75 createActions();
Jared Lindblomb4032e22013-01-17 23:50:51 -080076
Alexander Afanasyev83a53002013-01-24 11:12:01 -080077 // create tray icon
78 createTrayIcon();
Jared Lindblomb4032e22013-01-17 23:50:51 -080079
Alexander Afanasyev83a53002013-01-24 11:12:01 -080080 // set icon image
81 setIcon();
Jared Lindblom06405c42013-01-17 20:48:39 -080082
Alexander Afanasyev83a53002013-01-24 11:12:01 -080083 // show tray icon
84 m_trayIcon->show();
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -080085
86 // Dispatcher(const boost::filesystem::path &path, const std::string &localUserName, const Ccnx::Name &localPrefix,
87 // const std::string &sharedFolder, const boost::filesystem::path &rootDir,
88 // Ccnx::CcnxWrapperPtr ccnx, SchedulerPtr scheduler, int poolSize = 2);
89
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080090 m_dispatcher = new Dispatcher (m_username.toStdString (), m_sharedFolderName.toStdString (),
91 m_dirPath.toStdString (), make_shared<CcnxWrapper> ());
Jared Lindblomc8ffd592013-01-25 00:00:30 -080092
93 // Alex: this **must** be here, otherwise m_dirPath will be uninitialized
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080094 m_watcher = new FsWatcher (m_dirPath,
95 bind (&Dispatcher::Did_LocalFile_AddOrModify, m_dispatcher, _1),
96 bind (&Dispatcher::Did_LocalFile_Delete, m_dispatcher, _1));
Jared Lindblom06405c42013-01-17 20:48:39 -080097}
98
99ChronoShareGui::~ChronoShareGui()
100{
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800101 delete m_watcher; // stop filewatching ASAP
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -0800102 delete m_dispatcher; // stop dispatcher ASAP, but after watcher (to prevent triggering callbacks on deleted object)
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -0800103
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800104 // cleanup
105 delete m_trayIcon;
106 delete m_trayIconMenu;
107 delete m_openFolder;
108 delete m_viewSettings;
109 delete m_changeFolder;
110 delete m_quitProgram;
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800111
112 delete labelUsername;
113 delete labelSharedFolder;
114 delete editUsername;
115 delete editSharedFolder;
116 delete button;
117 delete label;
118 delete mainLayout;
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800119}
120
121void ChronoShareGui::openMessageBox(QString title, QString text)
122{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800123 QMessageBox messageBox(this);
124 messageBox.setWindowTitle(title);
125 messageBox.setText(text);
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800126
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800127 messageBox.setIconPixmap(QPixmap(":/images/friends-group-icon.png"));
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800128
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800129 messageBox.exec();
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800130}
131
132void ChronoShareGui::openMessageBox(QString title, QString text, QString infotext)
133{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800134 QMessageBox messageBox(this);
135 messageBox.setWindowTitle(title);
136 messageBox.setText(text);
137 messageBox.setInformativeText(infotext);
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800138
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800139 messageBox.setIconPixmap(QPixmap(":/images/friends-group-icon.png"));
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800140
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800141 messageBox.exec();
Jared Lindblom06405c42013-01-17 20:48:39 -0800142}
143
144void ChronoShareGui::createActions()
145{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800146 // create the "open folder" action
147 m_openFolder = new QAction(tr("&Open Folder"), this);
148 connect(m_openFolder, SIGNAL(triggered()), this, SLOT(openSharedFolder()));
Jared Lindblom06405c42013-01-17 20:48:39 -0800149
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800150 // create the "view settings" action
151 m_viewSettings = new QAction(tr("&View Settings"), this);
152 connect(m_viewSettings, SIGNAL(triggered()), this, SLOT(viewSettings()));
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800153
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800154 // create the "change folder" action
155 m_changeFolder = new QAction(tr("&Change Folder"), this);
156 connect(m_changeFolder, SIGNAL(triggered()), this, SLOT(openFileDialog()));
Jared Lindblomb4032e22013-01-17 23:50:51 -0800157
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800158 // create the "quit program" action
159 m_quitProgram = new QAction(tr("&Quit"), this);
160 connect(m_quitProgram, SIGNAL(triggered()), qApp, SLOT(quit()));
Jared Lindblom06405c42013-01-17 20:48:39 -0800161}
162
163void ChronoShareGui::createTrayIcon()
164{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800165 // create a new icon menu
166 m_trayIconMenu = new QMenu(this);
Jared Lindblom06405c42013-01-17 20:48:39 -0800167
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800168 // add actions to the menu
169 m_trayIconMenu->addAction(m_openFolder);
170 m_trayIconMenu->addSeparator();
171 m_trayIconMenu->addAction(m_viewSettings);
172 m_trayIconMenu->addAction(m_changeFolder);
173 m_trayIconMenu->addSeparator();
174 m_trayIconMenu->addAction(m_quitProgram);
Jared Lindblom06405c42013-01-17 20:48:39 -0800175
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800176 // create new tray icon
177 m_trayIcon = new QSystemTrayIcon(this);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800178
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800179 // associate the menu with the tray icon
180 m_trayIcon->setContextMenu(m_trayIconMenu);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800181
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800182 // handle left click of icon
183 connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconClicked(QSystemTrayIcon::ActivationReason)));
Jared Lindblom06405c42013-01-17 20:48:39 -0800184}
185
186void ChronoShareGui::setIcon()
187{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800188 // set the icon image
189 m_trayIcon->setIcon(QIcon(":/images/friends-group-icon.png"));
Jared Lindblom06405c42013-01-17 20:48:39 -0800190}
191
192void ChronoShareGui::openSharedFolder()
193{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800194 // Alex: isn't there an OS-independent way in QT for this?
Jared Lindblomb4032e22013-01-17 23:50:51 -0800195
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800196 // tell Finder to open the shared folder
197 QStringList scriptArgs;
198 scriptArgs << QLatin1String("-e")
199 << QString::fromLatin1("tell application \"Finder\" to reveal POSIX file \"%1\"")
200 .arg(m_dirPath);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800201
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800202 // execute the commands to make it happen
203 QProcess::execute(QLatin1String("/usr/bin/osascript"), scriptArgs);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800204
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800205 // clear command arguments
206 scriptArgs.clear();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800207
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800208 // tell Finder to appear
209 scriptArgs << QLatin1String("-e")
210 << QLatin1String("tell application \"Finder\" to activate");
211
212 // execute the commands to make it happen
213 QProcess::execute("/usr/bin/osascript", scriptArgs);
Jared Lindblom06405c42013-01-17 20:48:39 -0800214}
Jared Lindblomb4032e22013-01-17 23:50:51 -0800215
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800216void ChronoShareGui::changeSettings()
217{
218 if(!editUsername->text().isEmpty())
219 m_username = editUsername->text();
220 else
221 editUsername->setText(m_username);
222
223 if(!editSharedFolder->text().isEmpty())
224 m_sharedFolderName = editSharedFolder->text();
225 else
226 editSharedFolder->setText(m_sharedFolderName);
227
228 saveSettings();
229 this->hide();
230}
231
Jared Lindblomb4032e22013-01-17 23:50:51 -0800232void ChronoShareGui::openFileDialog()
233{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800234 // prompt user for new directory
235 QString tempPath = QFileDialog::getExistingDirectory(this, tr("Choose a new folder"),
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -0800236 m_dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
237 QFileInfo qFileInfo (tempPath);
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800238
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800239 if(qFileInfo.isDir())
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800240 {
241 m_dirPath = tempPath;
242 editSharedFolderPath->setText(m_dirPath);
243 }
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800244 else
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800245 {
246 openMessageBox ("Error", "Not a valid folder, Ignoring.");
247 }
Jared Lindblomb4032e22013-01-17 23:50:51 -0800248
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800249 _LOG_DEBUG ("Selected path: " << m_dirPath.toStdString ());
Jared Lindblomb4032e22013-01-17 23:50:51 -0800250
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800251 // save settings
252 saveSettings();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800253}
254
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800255void ChronoShareGui::trayIconClicked (QSystemTrayIcon::ActivationReason reason)
Jared Lindblomb4032e22013-01-17 23:50:51 -0800256{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800257 // if double clicked, open shared folder
258 if(reason == QSystemTrayIcon::DoubleClick)
Jared Lindblomb4032e22013-01-17 23:50:51 -0800259 {
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800260 openSharedFolder();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800261 }
262}
263
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800264void ChronoShareGui::viewSettings()
Jared Lindblomb4032e22013-01-17 23:50:51 -0800265{
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800266 //simple for now
267 this->show();
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800268}
269
270bool ChronoShareGui::loadSettings()
271{
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800272 bool successful = true;
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800273
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800274 // Load Settings
275 // QSettings settings(m_settingsFilePath, QSettings::NativeFormat);
276 QSettings settings (QSettings::NativeFormat, QSettings::UserScope, "irl.cs.ucla.edu", "ChronoShare");
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800277
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800278 // _LOG_DEBUG (lexical_cast<string> (settings.allKeys()));
279
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800280 if(settings.contains("username"))
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800281 {
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800282 m_username = settings.value("username", "admin").toString();
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800283 }
284 else
285 {
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800286 successful = false;
287 }
288
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800289 editUsername->setText(m_username);
290
291 if(settings.contains("sharedfoldername"))
292 {
293 m_sharedFolderName = settings.value("sharedfoldername", "shared").toString();
294 }
295 else
296 {
297 successful = false;
298 }
299
300 editSharedFolder->setText(m_sharedFolderName);
301
302 if(settings.contains("dirPath"))
303 {
304 m_dirPath = settings.value("dirPath", QDir::homePath()).toString();
305 }
306 else
307 {
308 successful = false;
309 }
310
311 editSharedFolderPath->setText(m_dirPath);
312
313 _LOG_DEBUG ("Found configured path: " << (successful ? m_dirPath.toStdString () : std::string("no")));
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800314
315 return successful;
Jared Lindblomb4032e22013-01-17 23:50:51 -0800316}
317
318void ChronoShareGui::saveSettings()
319{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800320 // Save Settings
321 // QSettings settings(m_settingsFilePath, QSettings::NativeFormat);
322 QSettings settings (QSettings::NativeFormat, QSettings::UserScope, "irl.cs.ucla.edu", "ChronoShare");
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800323
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800324 settings.setValue("dirPath", m_dirPath);
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800325 settings.setValue("username", m_username);
326 settings.setValue("sharedfoldername", m_sharedFolderName);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800327}
328
329void ChronoShareGui::closeEvent(QCloseEvent* event)
330{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800331 _LOG_DEBUG ("Close Event")
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800332 this->hide();
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800333 event->ignore(); // don't let the event propagate to the base class
Jared Lindblomb4032e22013-01-17 23:50:51 -0800334}
Jared Lindblomdc845f02013-01-18 17:29:40 -0800335
336#if WAF
337#include "chronosharegui.moc"
338#include "chronosharegui.cpp.moc"
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800339#endif