blob: 721421816947c27f620b2a3ac9aa6f860a82f3bd [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>
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -080019 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 * Zhenkai Zhu <zhenkai@cs.ucla.edu>
21 * Ilya Moiseenko <iliamo@ucla.edu>
Jared Lindblom06405c42013-01-17 20:48:39 -080022 */
23
24#include "chronosharegui.h"
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -080025
Alexander Afanasyev83a53002013-01-24 11:12:01 -080026#include "logging.h"
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080027#include "ccnx-wrapper.h"
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -080028#include <QValidator>
Zhenkai Zhuce04cb42013-02-25 15:29:31 -080029#include <QDir>
Zhenkai Zhu25e13582013-02-27 15:33:01 -080030#include <QFileInfo>
Zhenkai Zhuce04cb42013-02-25 15:29:31 -080031#include <QDesktopServices>
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -080032
33#include <boost/make_shared.hpp>
34
35using namespace boost;
36using namespace Ccnx;
Jared Lindblom06405c42013-01-17 20:48:39 -080037
Zhenkai Zhud9429222013-02-25 22:34:09 -080038static const string HTTP_SERVER_ADDRESS = "localhost";
39static const string HTTP_SERVER_PORT = "9001";
Zhenkai Zhu6b53f932013-03-02 20:46:02 -080040#ifdef _DEBUG
Zhenkai Zhu5c2475b2013-02-26 22:57:31 -080041static const string DOC_ROOT = "gui/html";
Zhenkai Zhu6b53f932013-03-02 20:46:02 -080042#else
43static const string DOC_ROOT = ":/html";
44#endif
Zhenkai Zhud9429222013-02-25 22:34:09 -080045static const QString ICON_PICTURE_QSTRING(":/images/friends-group-icon.png");
46
Alexander Afanasyev83a53002013-01-24 11:12:01 -080047INIT_LOGGER ("Gui");
48
49ChronoShareGui::ChronoShareGui(QWidget *parent)
Jared Lindblomc8ffd592013-01-25 00:00:30 -080050 : QDialog(parent)
Zhenkai Zhud5756312013-01-31 13:49:45 -080051 , m_watcher(0)
52 , m_dispatcher(0)
Zhenkai Zhud9429222013-02-25 22:34:09 -080053 , m_httpServer(0)
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -080054#ifdef ADHOC_SUPPORTED
55 , m_executor (1)
56#endif
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -080057#ifdef SPARKLE_SUPPORTED
Zhenkai Zhu8e3e9072013-02-28 15:40:51 -080058 , m_autoUpdate(new SparkleAutoUpdate(tr("http://irl.cs.ucla.edu/~zhenkai/chronoshare_dist/chronoshare.xml")))
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -080059#endif
Jared Lindblom06405c42013-01-17 20:48:39 -080060{
Jared Lindblomf4b900e2013-02-07 18:08:47 -080061 setWindowTitle("Settings");
Jared Lindblomc8ffd592013-01-25 00:00:30 -080062
Jared Lindblomd8b76ad2013-02-07 20:37:37 -080063 labelUsername = new QLabel("Username (hint: /<username>)");
Jared Lindblomc8ffd592013-01-25 00:00:30 -080064 labelSharedFolder = new QLabel("Shared Folder Name");
65 labelSharedFolderPath = new QLabel("Shared Folder Path");
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -080066
Zhenkai Zhud5756312013-01-31 13:49:45 -080067 QRegExp regex("(/[^/]+)+$");
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -080068 QValidator *prefixValidator = new QRegExpValidator(regex, this);
69
Jared Lindblomc8ffd592013-01-25 00:00:30 -080070 editUsername = new QLineEdit();
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -080071 editUsername->setValidator(prefixValidator);
72
73 QRegExp noPureWhiteSpace("^\\S+.*$");
74 QValidator *wsValidator = new QRegExpValidator(noPureWhiteSpace, this);
Jared Lindblomc8ffd592013-01-25 00:00:30 -080075 editSharedFolder = new QLineEdit();
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -080076 editSharedFolder->setValidator(wsValidator);
77
Jared Lindblomc8ffd592013-01-25 00:00:30 -080078 editSharedFolderPath = new QLineEdit();
79 editSharedFolderPath->setReadOnly(true);
80 QPalette pal = editSharedFolderPath->palette();
81 pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Disabled, QPalette::Base));
82 editSharedFolderPath->setPalette(pal);
83 button = new QPushButton("Submit");
Zhenkai Zhu630d0f12013-02-28 17:21:54 -080084
85 QString versionString = QString("Version: ChronoShare v%1").arg(CHRONOSHARE_VERSION);
86 label = new QLabel(versionString, this);
Jared Lindblomc8ffd592013-01-25 00:00:30 -080087
88 connect(button, SIGNAL(clicked()), this, SLOT(changeSettings()));
89
90 mainLayout = new QVBoxLayout; //vertically
91 mainLayout->addWidget(labelUsername);
92 mainLayout->addWidget(editUsername);
93 mainLayout->addWidget(labelSharedFolder);
94 mainLayout->addWidget(editSharedFolder);
95 mainLayout->addWidget(labelSharedFolderPath);
96 mainLayout->addWidget(editSharedFolderPath);
97 mainLayout->addWidget(button);
98 mainLayout->addWidget(label);
99 setLayout(mainLayout);
100
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800101 // create actions that result from clicking a menu option
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800102 createActionsAndMenu();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800103
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800104 // create tray icon
105 createTrayIcon();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800106
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800107 // set icon image
108 setIcon();
Jared Lindblom06405c42013-01-17 20:48:39 -0800109
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800110 // show tray icon
111 m_trayIcon->show();
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -0800112
113 // Dispatcher(const boost::filesystem::path &path, const std::string &localUserName, const Ccnx::Name &localPrefix,
114 // const std::string &sharedFolder, const boost::filesystem::path &rootDir,
115 // Ccnx::CcnxWrapperPtr ccnx, SchedulerPtr scheduler, int poolSize = 2);
116
Zhenkai Zhud5756312013-01-31 13:49:45 -0800117 // load settings
118 if(!loadSettings())
119 {
120 // prompt user to choose folder
121 openMessageBox("First Time Setup", "Please enter a username, shared folder name and choose the shared folder path on your local filesystem.");
122 viewSettings();
123 openFileDialog();
124 viewSettings();
125 }
126 else
127 {
128 startBackend();
129 }
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800130
131#ifdef ADHOC_SUPPORTED
132 m_executor.start ();
133#endif
Zhenkai Zhud5756312013-01-31 13:49:45 -0800134}
135
136void
137ChronoShareGui::startBackend()
138{
139 if (m_watcher != 0 && m_dispatcher != 0)
140 {
141 return;
142 }
143
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -0800144 m_dispatcher = new Dispatcher (m_username.toStdString (), m_sharedFolderName.toStdString (),
145 m_dirPath.toStdString (), make_shared<CcnxWrapper> ());
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800146
147 // Alex: this **must** be here, otherwise m_dirPath will be uninitialized
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -0800148 m_watcher = new FsWatcher (m_dirPath,
149 bind (&Dispatcher::Did_LocalFile_AddOrModify, m_dispatcher, _1),
Zhenkai Zhud1756272013-02-01 17:02:18 -0800150 bind (&Dispatcher::Did_LocalFile_Delete, m_dispatcher, _1));
Zhenkai Zhud9429222013-02-25 22:34:09 -0800151 QFileInfo indexHtmlInfo(":/html/index.html");
152 if (indexHtmlInfo.exists())
153 {
Zhenkai Zhu8da33652013-03-04 10:52:03 -0800154 try
155 {
156 m_httpServer = new http::server::server(HTTP_SERVER_ADDRESS, HTTP_SERVER_PORT, DOC_ROOT);
157 m_httpServerThread = boost::thread(&http::server::server::run, m_httpServer);
158 }
159 catch (std::exception &e)
160 {
161 _LOG_ERROR ("Start http server failed");
162 m_httpServer = 0; // just to make sure
163 QMessageBox msgBox;
164 msgBox.setText ("WARNING: Cannot start http server!");
165 msgBox.setIcon (QMessageBox::Warning);
166 msgBox.setInformativeText(QString("Starting http server failed. You will not be able to check history from web brower. Exception caused: %1").arg(e.what()));
167 msgBox.setStandardButtons(QMessageBox::Ok);
168 msgBox.exec();
169 }
Zhenkai Zhud9429222013-02-25 22:34:09 -0800170 }
171 else
172 {
173 _LOG_ERROR ("Http server doc root dir does not exist!");
Zhenkai Zhud9429222013-02-25 22:34:09 -0800174 }
Jared Lindblom06405c42013-01-17 20:48:39 -0800175}
176
177ChronoShareGui::~ChronoShareGui()
178{
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800179#ifdef ADHOC_SUPPORTED
180 m_executor.shutdown ();
181#endif
182
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800183 delete m_watcher; // stop filewatching ASAP
Alexander Afanasyev9ca444e2013-01-25 16:29:35 -0800184 delete m_dispatcher; // stop dispatcher ASAP, but after watcher (to prevent triggering callbacks on deleted object)
Zhenkai Zhu8da33652013-03-04 10:52:03 -0800185 if (m_httpServer != 0)
186 {
187 m_httpServer->handle_stop();
188 m_httpServerThread.join();
189 delete m_httpServer;
190 }
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -0800191
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800192 // cleanup
193 delete m_trayIcon;
194 delete m_trayIconMenu;
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800195#ifdef ADHOC_SUPPORTED
196 delete m_wifiAction;
197#endif
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800198#ifdef SPARKLE_SUPPORTED
199 delete m_autoUpdate;
Zhenkai Zhubb170d42013-02-25 13:48:59 -0800200 delete m_checkForUpdates;
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800201#endif
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800202 delete m_openFolder;
203 delete m_viewSettings;
204 delete m_changeFolder;
205 delete m_quitProgram;
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800206
207 delete labelUsername;
208 delete labelSharedFolder;
209 delete editUsername;
210 delete editSharedFolder;
211 delete button;
212 delete label;
213 delete mainLayout;
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800214}
215
216void ChronoShareGui::openMessageBox(QString title, QString text)
217{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800218 QMessageBox messageBox(this);
219 messageBox.setWindowTitle(title);
220 messageBox.setText(text);
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800221
Zhenkai Zhud9429222013-02-25 22:34:09 -0800222 messageBox.setIconPixmap(QPixmap(ICON_PICTURE_QSTRING));
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800223
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800224 messageBox.exec();
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800225}
226
227void ChronoShareGui::openMessageBox(QString title, QString text, QString infotext)
228{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800229 QMessageBox messageBox(this);
230 messageBox.setWindowTitle(title);
231 messageBox.setText(text);
232 messageBox.setInformativeText(infotext);
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800233
Zhenkai Zhud9429222013-02-25 22:34:09 -0800234 messageBox.setIconPixmap(QPixmap(ICON_PICTURE_QSTRING));
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800235
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800236 messageBox.exec();
Jared Lindblom06405c42013-01-17 20:48:39 -0800237}
238
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800239void ChronoShareGui::createActionsAndMenu()
Jared Lindblom06405c42013-01-17 20:48:39 -0800240{
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800241 _LOG_DEBUG ("Create actions");
242
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800243 // create the "open folder" action
244 m_openFolder = new QAction(tr("&Open Folder"), this);
245 connect(m_openFolder, SIGNAL(triggered()), this, SLOT(openSharedFolder()));
Jared Lindblom06405c42013-01-17 20:48:39 -0800246
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800247 m_openWeb = new QAction(tr("Open in &Browser"), this);
248 connect(m_openWeb, SIGNAL(triggered()), this, SLOT(openInWebBrowser()));
249
250 m_recentFilesMenu = new QMenu(tr("Recently Changed Files"), this);
251 for (int i = 0; i < 5; i++)
252 {
253 m_fileActions[i] = new QAction(this);
254 m_fileActions[i]->setVisible(false);
255 connect(m_fileActions[i], SIGNAL(triggered()), this, SLOT(openFile()));
256 m_recentFilesMenu->addAction(m_fileActions[i]);
257 }
258 connect(m_recentFilesMenu, SIGNAL(aboutToShow()), this, SLOT(updateRecentFilesMenu()));
259
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800260 // create the "view settings" action
261 m_viewSettings = new QAction(tr("&View Settings"), this);
262 connect(m_viewSettings, SIGNAL(triggered()), this, SLOT(viewSettings()));
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800263
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800264 // create the "change folder" action
265 m_changeFolder = new QAction(tr("&Change Folder"), this);
266 connect(m_changeFolder, SIGNAL(triggered()), this, SLOT(openFileDialog()));
Jared Lindblomb4032e22013-01-17 23:50:51 -0800267
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800268#ifdef ADHOC_SUPPORTED
269 // create "AdHoc Wifi" action
270 m_wifiAction = new QAction (tr("Enable AdHoc &WiFI"), m_trayIconMenu);
271 m_wifiAction->setChecked (false);
272 m_wifiAction->setCheckable (true);
273 connect (m_wifiAction, SIGNAL (toggled(bool)), this, SLOT(onAdHocChange(bool)));
274#endif
275
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800276#ifdef SPARKLE_SUPPORTED
Zhenkai Zhubb170d42013-02-25 13:48:59 -0800277 m_checkForUpdates = new QAction (tr("Check For Updates"), this);
278 connect (m_checkForUpdates, SIGNAL(triggered()), this, SLOT(onCheckForUpdates()));
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800279#endif
280
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800281 // create the "quit program" action
282 m_quitProgram = new QAction(tr("&Quit"), this);
283 connect(m_quitProgram, SIGNAL(triggered()), qApp, SLOT(quit()));
Jared Lindblom06405c42013-01-17 20:48:39 -0800284}
285
286void ChronoShareGui::createTrayIcon()
287{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800288 // create a new icon menu
289 m_trayIconMenu = new QMenu(this);
Jared Lindblom06405c42013-01-17 20:48:39 -0800290
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800291 // add actions to the menu
292 m_trayIconMenu->addAction(m_openFolder);
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800293 m_trayIconMenu->addAction(m_openWeb);
294 m_trayIconMenu->addMenu(m_recentFilesMenu);
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800295 m_trayIconMenu->addSeparator();
296 m_trayIconMenu->addAction(m_viewSettings);
297 m_trayIconMenu->addAction(m_changeFolder);
Alexander Afanasyeve8496a32013-03-03 16:10:43 -0800298
299#ifdef SPARKLE_SUPPORTED
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800300 m_trayIconMenu->addSeparator();
Zhenkai Zhu3857d712013-02-27 22:51:25 -0800301 m_trayIconMenu->addAction(m_checkForUpdates);
Alexander Afanasyeve8496a32013-03-03 16:10:43 -0800302#endif
303
304#ifdef ADHOC_SUPPORTED
Zhenkai Zhu3857d712013-02-27 22:51:25 -0800305 m_trayIconMenu->addSeparator();
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800306 m_trayIconMenu->addAction(m_wifiAction);
Alexander Afanasyeve8496a32013-03-03 16:10:43 -0800307#endif
308
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800309 m_trayIconMenu->addSeparator();
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800310 m_trayIconMenu->addAction(m_quitProgram);
Jared Lindblom06405c42013-01-17 20:48:39 -0800311
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800312 // create new tray icon
313 m_trayIcon = new QSystemTrayIcon(this);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800314
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800315#ifdef ADHOC_SUPPORTED
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800316 // associate the menu with the tray icon
317 m_trayIcon->setContextMenu(m_trayIconMenu);
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800318#endif
Jared Lindblomb4032e22013-01-17 23:50:51 -0800319
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800320 // handle left click of icon
321 connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconClicked(QSystemTrayIcon::ActivationReason)));
Jared Lindblom06405c42013-01-17 20:48:39 -0800322}
323
Alexander Afanasyev85a4ba02013-02-24 16:30:17 -0800324void
325ChronoShareGui::onAdHocChange (bool state)
326{
327#ifdef ADHOC_SUPPORTED
328 if (m_wifiAction->isChecked ())
329 {
330 QMessageBox msgBox;
331 msgBox.setText ("WARNING: your WiFi will be disconnected");
332 msgBox.setIcon (QMessageBox::Warning);
333 msgBox.setInformativeText("AdHoc WiFi will disconnect your current WiFi.\n Are you sure that you are OK with that?");
334 msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
335 msgBox.setDefaultButton(QMessageBox::Cancel);
336 int ret = msgBox.exec();
337
338 if (ret == QMessageBox::Cancel)
339 {
340 m_wifiAction->setChecked (false);
341 }
342 else
343 {
344
345 m_wifiAction->setText (tr("Disable AdHoc WiFI"));
346
347 // create adhoc
348 m_executor.execute (Adhoc::CreateAdhoc);
349 }
350 }
351 else
352 {
353 m_wifiAction->setText (tr("Enable AdHoc WiFI"));
354
355 // disable adhoc
356 m_executor.execute (Adhoc::DestroyAdhoc);
357
358 // a trick in DestroyAdhoc ensures that WiFi will be reconnected to a default WiFi
359 }
360#endif
361}
362
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800363void
364ChronoShareGui::onCheckForUpdates()
365{
Zhenkai Zhu249fbc72013-02-27 21:50:25 -0800366#ifdef SPARKLE_SUPPORTED
Zhenkai Zhu3857d712013-02-27 22:51:25 -0800367 cout << "+++++++++++ trying to update +++++++ " << endl;
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800368 m_autoUpdate->checkForUpdates();
Zhenkai Zhu3857d712013-02-27 22:51:25 -0800369 cout << "+++++++++++ end trying to update +++++++ " << endl;
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800370#endif
Zhenkai Zhu249fbc72013-02-27 21:50:25 -0800371}
Zhenkai Zhuaca6cb52013-02-24 23:34:03 -0800372
Jared Lindblom06405c42013-01-17 20:48:39 -0800373void ChronoShareGui::setIcon()
374{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800375 // set the icon image
Zhenkai Zhud9429222013-02-25 22:34:09 -0800376 m_trayIcon->setIcon(QIcon(ICON_PICTURE_QSTRING));
Jared Lindblom06405c42013-01-17 20:48:39 -0800377}
378
379void ChronoShareGui::openSharedFolder()
380{
Zhenkai Zhuce04cb42013-02-25 15:29:31 -0800381 QString path = QDir::toNativeSeparators(m_dirPath);
382 QDesktopServices::openUrl(QUrl("file:///" + path));
Jared Lindblom06405c42013-01-17 20:48:39 -0800383}
Jared Lindblomb4032e22013-01-17 23:50:51 -0800384
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800385void ChronoShareGui::openInWebBrowser()
386{
Alexander Afanasyevf63a5142013-02-28 02:21:42 -0800387 QUrl url ("http://localhost:9001/");
388 url.setFragment ("fileList&"
389 "user=" + QUrl::toPercentEncoding (m_username) + "&"
390 "folder=" + QUrl::toPercentEncoding (m_sharedFolderName));
391
392 // i give up. there is double encoding and I have no idea how to fight it...
393 QDesktopServices::openUrl (url);
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800394}
395
396void ChronoShareGui::openFile()
397{
398 // figure out who sent the signal
399 QAction *pAction = qobject_cast<QAction*>(sender());
400 if (pAction->isEnabled())
401 {
402 // we stored full path of the file in this toolTip field
403#ifdef Q_WS_MAC
404 // we do some hack so we could show the file in Finder highlighted
405 QStringList args;
406 args << "-e";
407 args << "tell application \"Finder\"";
408 args << "-e";
409 args << "activate";
410 args << "-e";
411 args << "select POSIX file \"" + pAction->toolTip() + "/" + pAction->text() + "\"";
412 args << "-e";
413 args << "end tell";
414 QProcess::startDetached("osascript", args);
415#else
416 // too bad qt couldn't do highlighting for Linux (or Mac)
417 QDesktopServices::openUrl(QUrl("file:///" + pAction->toolTip()));
418#endif
419 }
420}
421
422void ChronoShareGui::updateRecentFilesMenu()
423{
424 for (int i = 0; i < 5; i++)
425 {
426 m_fileActions[i]->setVisible(false);
427 }
428 m_dispatcher->LookupRecentFileActions(boost::bind(&ChronoShareGui::checkFileAction, this, _1, _2, _3), 5);
429}
430
431void ChronoShareGui::checkFileAction (const std::string &filename, int action, int index)
432{
433 QString fullPath = m_dirPath + "/" + filename.c_str();
434 QFileInfo fileInfo(fullPath);
435 if (fileInfo.exists())
436 {
437 // This is a hack, we just use some field to store the path
438 m_fileActions[index]->setToolTip(fileInfo.absolutePath());
439 m_fileActions[index]->setEnabled(true);
440 }
441 else
442 {
443 // after half an hour frustrating test and search around,
444 // I think it's the problem of Qt.
445 // According to the Qt doc, the action cannot be clicked
446 // and the area would be grey, but it didn't happen
447 // User can still trigger the action, and not greyed
448 // added check in SLOT to see if the action is "enalbed"
449 // as a remedy
450 // Give up at least for now
451 m_fileActions[index]->setEnabled(false);
452 // UPDATE, file not fetched yet
453 if (action == 0)
454 {
455 QFont font;
456 // supposed by change the font, didn't happen
457 font.setWeight(QFont::Light);
458 m_fileActions[index]->setFont(font);
459 m_fileActions[index]->setToolTip(tr("Fetching..."));
460 }
461 // DELETE
462 else
463 {
464 QFont font;
465 // supposed by change the font, didn't happen
466 font.setStrikeOut(true);
467 m_fileActions[index]->setFont(font);
468 m_fileActions[index]->setToolTip(tr("Deleted..."));
469 }
470 }
471 m_fileActions[index]->setText(fileInfo.fileName());
472 m_fileActions[index]->setVisible(true);
473}
474
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800475void ChronoShareGui::changeSettings()
476{
477 if(!editUsername->text().isEmpty())
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -0800478 m_username = editUsername->text().trimmed();
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800479 else
480 editUsername->setText(m_username);
481
482 if(!editSharedFolder->text().isEmpty())
Zhenkai Zhuf3ea97a2013-01-30 15:20:52 -0800483 m_sharedFolderName = editSharedFolder->text().trimmed();
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800484 else
485 editSharedFolder->setText(m_sharedFolderName);
486
487 saveSettings();
488 this->hide();
Zhenkai Zhud5756312013-01-31 13:49:45 -0800489
490 startBackend();
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800491}
492
Jared Lindblomb4032e22013-01-17 23:50:51 -0800493void ChronoShareGui::openFileDialog()
494{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800495 // prompt user for new directory
496 QString tempPath = QFileDialog::getExistingDirectory(this, tr("Choose a new folder"),
Alexander Afanasyev9e5a4702013-01-24 13:15:23 -0800497 m_dirPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
498 QFileInfo qFileInfo (tempPath);
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800499
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800500 if(qFileInfo.isDir())
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800501 {
502 m_dirPath = tempPath;
503 editSharedFolderPath->setText(m_dirPath);
504 }
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800505 else
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800506 {
507 openMessageBox ("Error", "Not a valid folder, Ignoring.");
508 }
Jared Lindblomb4032e22013-01-17 23:50:51 -0800509
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800510 _LOG_DEBUG ("Selected path: " << m_dirPath.toStdString ());
Jared Lindblomb4032e22013-01-17 23:50:51 -0800511
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800512 // save settings
513 saveSettings();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800514}
515
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800516void ChronoShareGui::trayIconClicked (QSystemTrayIcon::ActivationReason reason)
Jared Lindblomb4032e22013-01-17 23:50:51 -0800517{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800518 // if double clicked, open shared folder
519 if(reason == QSystemTrayIcon::DoubleClick)
Jared Lindblomb4032e22013-01-17 23:50:51 -0800520 {
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800521 openSharedFolder();
Jared Lindblomb4032e22013-01-17 23:50:51 -0800522 }
523}
524
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800525void ChronoShareGui::viewSettings()
Jared Lindblomb4032e22013-01-17 23:50:51 -0800526{
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800527 //simple for now
528 this->show();
Zhenkai Zhud5756312013-01-31 13:49:45 -0800529 this->raise();
530 this->activateWindow();
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800531}
532
533bool ChronoShareGui::loadSettings()
534{
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800535 bool successful = true;
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800536
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800537 // Load Settings
538 // QSettings settings(m_settingsFilePath, QSettings::NativeFormat);
539 QSettings settings (QSettings::NativeFormat, QSettings::UserScope, "irl.cs.ucla.edu", "ChronoShare");
Jared Lindblom5d7e51e2013-01-18 00:59:34 -0800540
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800541 // _LOG_DEBUG (lexical_cast<string> (settings.allKeys()));
542
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800543 if(settings.contains("username"))
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800544 {
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800545 m_username = settings.value("username", "admin").toString();
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800546 }
547 else
548 {
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800549 successful = false;
550 }
551
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800552 editUsername->setText(m_username);
553
554 if(settings.contains("sharedfoldername"))
555 {
556 m_sharedFolderName = settings.value("sharedfoldername", "shared").toString();
557 }
558 else
559 {
560 successful = false;
561 }
562
563 editSharedFolder->setText(m_sharedFolderName);
564
565 if(settings.contains("dirPath"))
566 {
567 m_dirPath = settings.value("dirPath", QDir::homePath()).toString();
568 }
569 else
570 {
571 successful = false;
572 }
573
574 editSharedFolderPath->setText(m_dirPath);
575
576 _LOG_DEBUG ("Found configured path: " << (successful ? m_dirPath.toStdString () : std::string("no")));
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800577
578 return successful;
Jared Lindblomb4032e22013-01-17 23:50:51 -0800579}
580
581void ChronoShareGui::saveSettings()
582{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800583 // Save Settings
584 // QSettings settings(m_settingsFilePath, QSettings::NativeFormat);
585 QSettings settings (QSettings::NativeFormat, QSettings::UserScope, "irl.cs.ucla.edu", "ChronoShare");
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800586
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800587 settings.setValue("dirPath", m_dirPath);
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800588 settings.setValue("username", m_username);
589 settings.setValue("sharedfoldername", m_sharedFolderName);
Jared Lindblomb4032e22013-01-17 23:50:51 -0800590}
591
592void ChronoShareGui::closeEvent(QCloseEvent* event)
593{
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800594 _LOG_DEBUG ("Close Event")
Jared Lindblomc8ffd592013-01-25 00:00:30 -0800595 this->hide();
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800596 event->ignore(); // don't let the event propagate to the base class
Jared Lindblomb4032e22013-01-17 23:50:51 -0800597}
Jared Lindblomdc845f02013-01-18 17:29:40 -0800598
599#if WAF
600#include "chronosharegui.moc"
601#include "chronosharegui.cpp.moc"
Alexander Afanasyev83a53002013-01-24 11:12:01 -0800602#endif