show recent files; supposed works, but glitch exists
probably due to Qt bug.
open web;
Change-Id: Ib9df50de82d7af659a09978e9d0aa0a5c540a041
diff --git a/gui/chronosharegui.cpp b/gui/chronosharegui.cpp
index 8d811e8..9fdd630 100644
--- a/gui/chronosharegui.cpp
+++ b/gui/chronosharegui.cpp
@@ -27,6 +27,7 @@
#include "ccnx-wrapper.h"
#include <QValidator>
#include <QDir>
+#include <QFileInfo>
#include <QDesktopServices>
#include <boost/make_shared.hpp>
@@ -92,7 +93,7 @@
setLayout(mainLayout);
// create actions that result from clicking a menu option
- createActions();
+ createActionsAndMenu();
// create tray icon
createTrayIcon();
@@ -211,7 +212,7 @@
messageBox.exec();
}
-void ChronoShareGui::createActions()
+void ChronoShareGui::createActionsAndMenu()
{
_LOG_DEBUG ("Create actions");
@@ -219,6 +220,19 @@
m_openFolder = new QAction(tr("&Open Folder"), this);
connect(m_openFolder, SIGNAL(triggered()), this, SLOT(openSharedFolder()));
+ m_openWeb = new QAction(tr("Open in &Browser"), this);
+ connect(m_openWeb, SIGNAL(triggered()), this, SLOT(openInWebBrowser()));
+
+ m_recentFilesMenu = new QMenu(tr("Recently Changed Files"), this);
+ for (int i = 0; i < 5; i++)
+ {
+ m_fileActions[i] = new QAction(this);
+ m_fileActions[i]->setVisible(false);
+ connect(m_fileActions[i], SIGNAL(triggered()), this, SLOT(openFile()));
+ m_recentFilesMenu->addAction(m_fileActions[i]);
+ }
+ connect(m_recentFilesMenu, SIGNAL(aboutToShow()), this, SLOT(updateRecentFilesMenu()));
+
// create the "view settings" action
m_viewSettings = new QAction(tr("&View Settings"), this);
connect(m_viewSettings, SIGNAL(triggered()), this, SLOT(viewSettings()));
@@ -252,6 +266,8 @@
// add actions to the menu
m_trayIconMenu->addAction(m_openFolder);
+ m_trayIconMenu->addAction(m_openWeb);
+ m_trayIconMenu->addMenu(m_recentFilesMenu);
m_trayIconMenu->addSeparator();
m_trayIconMenu->addAction(m_viewSettings);
m_trayIconMenu->addAction(m_changeFolder);
@@ -331,6 +347,90 @@
QDesktopServices::openUrl(QUrl("file:///" + path));
}
+void ChronoShareGui::openInWebBrowser()
+{
+ QDesktopServices::openUrl(QUrl("http://localhost:9001"));
+}
+
+void ChronoShareGui::openFile()
+{
+ // figure out who sent the signal
+ QAction *pAction = qobject_cast<QAction*>(sender());
+ if (pAction->isEnabled())
+ {
+ // we stored full path of the file in this toolTip field
+#ifdef Q_WS_MAC
+ // we do some hack so we could show the file in Finder highlighted
+ QStringList args;
+ args << "-e";
+ args << "tell application \"Finder\"";
+ args << "-e";
+ args << "activate";
+ args << "-e";
+ args << "select POSIX file \"" + pAction->toolTip() + "/" + pAction->text() + "\"";
+ args << "-e";
+ args << "end tell";
+ QProcess::startDetached("osascript", args);
+#else
+ // too bad qt couldn't do highlighting for Linux (or Mac)
+ QDesktopServices::openUrl(QUrl("file:///" + pAction->toolTip()));
+#endif
+ }
+}
+
+void ChronoShareGui::updateRecentFilesMenu()
+{
+ for (int i = 0; i < 5; i++)
+ {
+ m_fileActions[i]->setVisible(false);
+ }
+ m_dispatcher->LookupRecentFileActions(boost::bind(&ChronoShareGui::checkFileAction, this, _1, _2, _3), 5);
+}
+
+void ChronoShareGui::checkFileAction (const std::string &filename, int action, int index)
+{
+ QString fullPath = m_dirPath + "/" + filename.c_str();
+ QFileInfo fileInfo(fullPath);
+ if (fileInfo.exists())
+ {
+ // This is a hack, we just use some field to store the path
+ m_fileActions[index]->setToolTip(fileInfo.absolutePath());
+ m_fileActions[index]->setEnabled(true);
+ }
+ else
+ {
+ // after half an hour frustrating test and search around,
+ // I think it's the problem of Qt.
+ // According to the Qt doc, the action cannot be clicked
+ // and the area would be grey, but it didn't happen
+ // User can still trigger the action, and not greyed
+ // added check in SLOT to see if the action is "enalbed"
+ // as a remedy
+ // Give up at least for now
+ m_fileActions[index]->setEnabled(false);
+ // UPDATE, file not fetched yet
+ if (action == 0)
+ {
+ QFont font;
+ // supposed by change the font, didn't happen
+ font.setWeight(QFont::Light);
+ m_fileActions[index]->setFont(font);
+ m_fileActions[index]->setToolTip(tr("Fetching..."));
+ }
+ // DELETE
+ else
+ {
+ QFont font;
+ // supposed by change the font, didn't happen
+ font.setStrikeOut(true);
+ m_fileActions[index]->setFont(font);
+ m_fileActions[index]->setToolTip(tr("Deleted..."));
+ }
+ }
+ m_fileActions[index]->setText(fileInfo.fileName());
+ m_fileActions[index]->setVisible(true);
+}
+
void ChronoShareGui::changeSettings()
{
if(!editUsername->text().isEmpty())
diff --git a/gui/chronosharegui.h b/gui/chronosharegui.h
index c094f3e..6497d5f 100644
--- a/gui/chronosharegui.h
+++ b/gui/chronosharegui.h
@@ -63,6 +63,12 @@
// open the shared folder
void openSharedFolder();
+ void openFile();
+
+ void openInWebBrowser();
+
+ void updateRecentFilesMenu();
+
// open file dialog
void openFileDialog();
@@ -82,8 +88,9 @@
#endif
private:
+ void checkFileAction(const std::string &, int, int);
// create actions that result from clicking a menu option
- void createActions();
+ void createActionsAndMenu();
// create tray icon
void createTrayIcon();
@@ -119,6 +126,9 @@
QAction* m_changeFolder; // change the shared folder action
QAction* m_quitProgram; // quit program action
QAction *m_checkForUpdates;
+ QAction *m_openWeb;
+ QMenu *m_recentFilesMenu;
+ QAction *m_fileActions[5];
QAction *m_wifiAction;
diff --git a/src/action-log.cc b/src/action-log.cc
index 9d96efc..740430f 100644
--- a/src/action-log.cc
+++ b/src/action-log.cc
@@ -727,6 +727,38 @@
return (limit == 1); // more data is available
}
+void
+ActionLog::LookupRecentFileActions(const boost::function<void (const string &, int, int)> &visitor, int limit)
+{
+ sqlite3_stmt *stmt;
+
+ sqlite3_prepare_v2 (m_db,
+ "SELECT AL.filename, AL.action"
+ " FROM ActionLog AL"
+ " JOIN "
+ " (SELECT filename, MAX(action_timestamp) AS action_timestamp "
+ " FROM ActionLog "
+ " GROUP BY filename ) AS GAL"
+ " ON AL.filename = GAL.filename AND AL.action_timestamp = GAL.action_timestamp "
+ " ORDER BY AL.action_timestamp DESC "
+ " LIMIT ?;",
+ -1, &stmt, 0);
+ _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
+ sqlite3_bind_int(stmt, 1, limit);
+ int index = 0;
+ while (sqlite3_step(stmt) == SQLITE_ROW)
+ {
+ std::string filename(reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
+ int action = sqlite3_column_int (stmt, 1);
+ visitor(filename, action, index);
+ index++;
+ }
+
+ _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
+
+ sqlite3_finalize (stmt);
+}
+
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
diff --git a/src/action-log.h b/src/action-log.h
index cef0a65..6345281 100644
--- a/src/action-log.h
+++ b/src/action-log.h
@@ -109,6 +109,9 @@
LookupActionsInFolderRecursively (const boost::function<void (const Ccnx::Name &name, sqlite3_int64 seq_no, const ActionItem &)> &visitor,
const std::string &folder, int offset=0, int limit=-1);
+ void
+ LookupRecentFileActions(const boost::function<void (const std::string &, int, int)> &visitor, int limit = 5);
+
//
inline FileStatePtr
GetFileState ();
diff --git a/src/dispatcher.h b/src/dispatcher.h
index 0455ff0..d3b6bc3 100644
--- a/src/dispatcher.h
+++ b/src/dispatcher.h
@@ -75,6 +75,9 @@
HashPtr
SyncRoot() { return m_core->root(); }
+ inline void
+ LookupRecentFileActions(const boost::function<void(const std::string &, int, int)> &visitor, int limit) { m_actionLog->LookupRecentFileActions(visitor, limit); }
+
private:
void
Did_LocalFile_AddOrModify_Execute (boost::filesystem::path relativeFilepath); // cannot be const & for Execute event!!! otherwise there will be segfault