Skip to content

Commit

Permalink
Refactored code and Implemented Factory Pattern for different Window …
Browse files Browse the repository at this point in the history
…Trackers
  • Loading branch information
SySyAli committed Dec 26, 2023
1 parent 11adb30 commit b33c569
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 109 deletions.
10 changes: 5 additions & 5 deletions AppEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "AppEntry.h"
#include <utility>

AppEntry::AppEntry(std::string ti, const std::time_t sT, const std::time_t eT, const long long i)
AppEntry::AppEntry(std::string ti, const TimePoint sT, const TimePoint eT, const long long i)
: id(i)
, title(std::move(ti))
, startTime(sT)
Expand Down Expand Up @@ -34,22 +34,22 @@ std::string AppEntry::getTitle() const
return title;
}

void AppEntry::setStartTime(std::time_t sT)
void AppEntry::setStartTime(AppEntry::TimePoint sT)
{
startTime = sT;
}

std::time_t AppEntry::getStartTime() const
AppEntry::TimePoint AppEntry::getStartTime() const
{
return startTime;
}

void AppEntry::setEndTime(std::time_t eT)
void AppEntry::setEndTime(AppEntry::TimePoint eT)
{
endTime = eT;
}

std::time_t AppEntry::getEndTime() const
AppEntry::TimePoint AppEntry::getEndTime() const
{
return endTime;
}
Expand Down
21 changes: 13 additions & 8 deletions AppEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <ctime>
#include <string>
#include <chrono>

/**
* @class AppEntry
Expand All @@ -13,8 +14,12 @@
*/
class AppEntry {
public:
// Use std::chrono::system_clock::time_point for time tracking
using TimePoint = std::chrono::system_clock::time_point;

// alternate ctor - defaults to an empty AppEntry.
explicit AppEntry(std::string ti = "", std::time_t sT = 0, std::time_t eT = 0, long long i = 0);
explicit AppEntry(std::string ti = "", TimePoint sT = std::chrono::system_clock::now(), TimePoint
eT = std::chrono::system_clock::now(), long long i = 0);

// defaulted copy ctor
AppEntry(const AppEntry& copy) = default;
Expand All @@ -29,24 +34,24 @@ class AppEntry {
void setTitle(const std::string& t);
[[nodiscard]] std::string getTitle() const;

void setStartTime(std::time_t sT);
[[nodiscard]] std::time_t getStartTime() const;
void setStartTime(TimePoint sT);
[[nodiscard]] TimePoint getStartTime() const;

void setEndTime(std::time_t sT);
[[nodiscard]] std::time_t getEndTime() const;
void setEndTime(TimePoint sT);
[[nodiscard]] TimePoint getEndTime() const;

// returns whether title is empty
bool isEmpty() const;
[[nodiscard]] bool isEmpty() const;

private:
// id of AppEntry
long long id;
// title of AppEntry
std::string title;
// startTime of Window Visitation
std::time_t startTime;
TimePoint startTime;
// endTime of Window Visitation
std::time_t endTime;
TimePoint endTime;
};

#endif // APPENTRY_H
96 changes: 26 additions & 70 deletions AppTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,103 +6,59 @@
#include "AppTracker.h"
#include "AppEntry.h"
#include <iostream>
#include <algorithm>

AppTracker::AppTracker()
{
#ifdef _WIN32
#include <windows.h>
windowTracker = std::make_unique<WindowsTracker>();
#elif __linux__
windowTracker = std::make_unique<LinuxTracker>();
#else
throw std::runtime_error("Unsupported OS");
#endif
}

AppTracker::AppTracker()
: dbManager(DatabaseManager())
, tracking(true)
std::ostream& operator<<(std::ostream& os, AppTracker& a)
{
std::vector<AppEntry> appEntries = a.getAppEntries();

std::for_each(appEntries.begin(), appEntries.end(), [&os](AppEntry& entry) {
const std::time_t t_s = std::chrono::system_clock::to_time_t(entry.getStartTime());
const std::time_t t_e = std::chrono::system_clock::to_time_t(entry.getEndTime());
os << "ID: " << entry.getID() << ", Title: " << entry.getTitle()
<< ", Start Time: " << std::ctime(&t_s) << ", End Time: " << std::ctime(&t_e)
<< '\n';
});
return os;
}

void AppTracker::startTracking()
{
#ifdef _WIN32
startTrackingWindows();
#elif __linux
startTrackingLinux();
#else
throw std::runtime_error("Operating Systems other than Windows have not been supported yet!");
#endif
windowTracker->startTracking();
}

void AppTracker::stopTracking()
{
tracking = false;
windowTracker->stopTracking();
}

std::vector<AppEntry> AppTracker::getAppEntries()
{
return dbManager.getAppEntries();
return windowTracker->getAppEntries();
}

void AppTracker::clearTracking()
{
dbManager.clearData();
windowTracker->clearTracking();
}

DatabaseManager& AppTracker::getDatabaseManager()
{
return dbManager;
return windowTracker->getDatabaseManager();
}

bool AppTracker::getTrackingBool() const
{
return tracking;
}
#ifdef _WIN32
void AppTracker::startTrackingWindows()
{
char windowTitle[256];
AppEntry prevEntry;

while (tracking) {
HWND hwnd = GetForegroundWindow();
GetWindowText(hwnd, windowTitle, sizeof(windowTitle));
std::string title(windowTitle);
time_t now = time(nullptr);
// convert now to string form
char dt[26];

errno_t err = ctime_s(dt, sizeof(dt), &now);

if (err) {
throw std::runtime_error("Error converting time");
}

clock_t curTime = clock();

if (!title.empty()) {
// handle the first entry
if (prevEntry.isEmpty()) {
std::cout << "Starting time for " << title << " : " << dt;

prevEntry.setTitle(title);
prevEntry.setStartTime(clock());
} else if (prevEntry.getTitle() != title) {
prevEntry.setEndTime(curTime);
std::cout << "Ending time for " << prevEntry.getTitle() << " : " << dt;
std::cout << "Duration for " << prevEntry.getTitle() << " : "
<< (prevEntry.getEndTime() - prevEntry.getStartTime())
/ (long long)CLOCKS_PER_SEC
<< std::endl;

// insert the appEntry
dbManager.insertData(prevEntry);

// figure out the time spent at the website
std::cout << "Starting time for " << title << " : " << dt << std::endl;
prevEntry.setTitle(title);
prevEntry.setStartTime(curTime);
}
}
Sleep(1000); // Check every second, check if this should be changed
}
}
#elif __linux
void AppTracker::startTrackingLinux(){
throw std::runtime_error("linux is not implemented yet!");
return windowTracker->getTrackingBool();
}
#endif
18 changes: 6 additions & 12 deletions AppTracker.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#ifndef APPTRACKER_H
#define APPTRACKER_H

#include <memory>
#include "DatabaseManager.h"
#include "IWindowInterface.h"

/**
* @class AppTracker
Expand All @@ -14,6 +16,9 @@ class AppTracker {
// default ctor.
AppTracker();

// operator overload that prints results
friend std::ostream& operator<<(std::ostream& os, AppTracker& a);

// startTracking Method - throws error if OS is not windows. controlled by
// tracking boolean
void startTracking();
Expand All @@ -34,18 +39,7 @@ class AppTracker {
[[nodiscard]] bool getTrackingBool() const;

private:
// DatabaseManager for the AppTracker
DatabaseManager dbManager;
// boolean for tracking
bool tracking;
#ifdef _WIN32
// startTracking Method - windows implementation
void startTrackingWindows();
#elif __linux__
void startTrackingLinux();
// TODO: Linux implementation
// TODO: MacOS implementation
#endif
std::unique_ptr<IWindowInterface> windowTracker;
};

#endif // APPTRACKER_H
14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,19 @@ include_directories(${googletest_SOURCE_DIR}/googletest/include)
add_executable(desktop_screentime main.cpp
AppTracker.cpp
DatabaseManager.cpp
AppEntry.cpp)
AppEntry.cpp
IWindowInterface.cpp
)

## Link SQLite3 to the executable ##
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES} pthread)
# Set compiler flags
if(MSVC)
# Using Microsoft Visual C++
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES})
else()
# Assuming GCC or Clang
target_link_libraries(desktop_screentime PRIVATE ${SQLite3_LIBRARIES} pthread)
endif()
target_include_directories(desktop_screentime PRIVATE ${SQLite3_INCLUDE_DIRS})

# Testing Executable
Expand All @@ -51,6 +60,7 @@ set(SOURCE_FILES
AppTracker.cpp
DatabaseManager.cpp
AppEntry.cpp
IWindowInterface.cpp
)

# Make the project root directory the working directory when we run
Expand Down
21 changes: 13 additions & 8 deletions DatabaseManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ DatabaseManager::DatabaseManager()

void DatabaseManager::insertData(AppEntry& appEntry)
{
auto startEpoch = std::chrono::system_clock::to_time_t(appEntry.getStartTime());
auto endEpoch = std::chrono::system_clock::to_time_t(appEntry.getEndTime());

const char* insertSql = "INSERT INTO AppUsage (title, startTime, endTime) VALUES (?, ?, ?)";
sqlite3_stmt* stmt;
int rc = sqlite3_prepare_v2(db, insertSql, -1, &stmt, nullptr);

if (rc == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, appEntry.getTitle().c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int64(stmt, 2, static_cast<long long>(appEntry.getStartTime()));
sqlite3_bind_int64(stmt, 3, static_cast<long long>(appEntry.getEndTime()));
sqlite3_bind_int64(stmt, 2, startEpoch);
sqlite3_bind_int64(stmt, 3, endEpoch);

rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE) {
Expand All @@ -55,9 +58,11 @@ void DatabaseManager::queryData()
{
auto currEntries = getAppEntries();
std::for_each(appEntries.begin(), appEntries.end(), [](AppEntry& entry) {
const std::time_t t_s = std::chrono::system_clock::to_time_t(entry.getStartTime());
const std::time_t t_e = std::chrono::system_clock::to_time_t(entry.getEndTime());
std::cout << "ID: " << entry.getID() << ", Title: " << entry.getTitle()
<< ", Start Time: " << entry.getStartTime()
<< ", End Time: " << entry.getEndTime() << std::endl;
<< ", Start Time: " << std::ctime(&t_s) << ", End Time: " << std::ctime(&t_e)
<< '\n';
});
}

Expand Down Expand Up @@ -90,14 +95,14 @@ std::vector<AppEntry> DatabaseManager::getAppEntries()
while (sqlite3_step(stmt) == SQLITE_ROW) {
int id = sqlite3_column_int(stmt, 0);
const char* title = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
auto startTime = static_cast<std::time_t>(sqlite3_column_int64(stmt, 2));
auto endTime = static_cast<std::time_t>(sqlite3_column_int64(stmt, 3));
auto startEpoch = sqlite3_column_int64(stmt, 2);
auto endEpoch = sqlite3_column_int64(stmt, 3);

AppEntry entry;
entry.setID(id);
entry.setTitle(std::string(title));
entry.setStartTime(startTime);
entry.setEndTime(endTime);
entry.setStartTime(std::chrono::system_clock::from_time_t(startEpoch));
entry.setEndTime(std::chrono::system_clock::from_time_t(endEpoch));

entries.push_back(entry);
}
Expand Down
Loading

0 comments on commit b33c569

Please sign in to comment.