Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandrePTJ committed Mar 27, 2023
2 parents ac31985 + 77f2b1d commit 32a2e9a
Show file tree
Hide file tree
Showing 33 changed files with 958 additions and 253 deletions.
3 changes: 2 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Checks: >
performance-*,
readability-*,
-readability-convert-member-functions-to-static,
-readability-qualified-auto
-readability-qualified-auto,
-readability-identifier-length
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none
8 changes: 7 additions & 1 deletion .idea/kemai.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]


## [0.9.0] - 2023-03-27

Special thanks to @shrippen for its support through [sponsorship](https://github.com/sponsors/AlexandrePTJ).

### Added
- Periodic check of current timesheet [#80](https://github.com/AlexandrePTJ/kemai/issues/80).

### Fixed
- Regression resetting dropdown fields when stopping timesheet [#77](https://github.com/AlexandrePTJ/kemai/issues/77).

### Changed
- Allow selection of project without first selecting customer [#74](https://github.com/AlexandrePTJ/kemai/issues/74).
- Improve Loading of Customer / Projects / Activities [#44](https://github.com/AlexandrePTJ/kemai/issues/44).
- Improve filter on Customer / Projects / Activities [#75](https://github.com/AlexandrePTJ/kemai/issues/75).


## [0.8.0] - 2023-03-14

### Added
- TimeSheet description and tags are saved on stop [#43](https://github.com/AlexandrePTJ/kemai/issues/43).
- Option to enable/disable Kemai's update check [#68](https://github.com/AlexandrePTJ/kemai/issues/68).
Expand Down Expand Up @@ -115,7 +134,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Initial version.


[Unreleased]: https://github.com/AlexandrePTJ/kemai/compare/0.7.1...HEAD
[Unreleased]: https://github.com/AlexandrePTJ/kemai/compare/0.9.0...HEAD
[0.9.0]: https://github.com/AlexandrePTJ/kemai/compare/0.8.0...0.9.0
[0.8.0]: https://github.com/AlexandrePTJ/kemai/compare/0.7.1...0.8.0
[0.7.1]: https://github.com/AlexandrePTJ/kemai/compare/0.7.0...0.7.1
[0.7.0]: https://github.com/AlexandrePTJ/kemai/compare/0.6.0...0.7.0
[0.6.0]: https://github.com/AlexandrePTJ/kemai/compare/0.5.0...0.6.0
Expand Down
7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.11)
project(KemaiProject VERSION 0.8.0 LANGUAGES CXX)
project(KemaiProject VERSION 0.9.0 LANGUAGES CXX)

# Point CMake to the custom modules
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/cmake)
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})

# Common configuration
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Setup Conan
Expand Down Expand Up @@ -38,6 +38,9 @@ endif ()
# Setup other dependencies
find_package(spdlog REQUIRED)
find_package(magic_enum REQUIRED)
if (APPLE)
find_package(range-v3 REQUIRED)
endif()

# Write version to file to ease packaging
file(WRITE ${CMAKE_BINARY_DIR}/version.txt ${PROJECT_VERSION})
Expand Down
11 changes: 11 additions & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from conan import ConanFile


class KemaiConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake_find_package"
requires = ("spdlog/1.11.0", "magic_enum/0.8.2")

def requirements(self):
if self.settings.os == "Macos":
self.requires("range-v3/0.12.0")
6 changes: 0 additions & 6 deletions conanfile.txt

This file was deleted.

12 changes: 11 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ configure_file(kemai_config.h.in ${PROJECT_BINARY_DIR}/kemai_config.h)
# Sources
set(SRCS
client/kimaiapi.cpp
client/kimaiCache.cpp
client/kimaiclient.cpp
client/kimaireply.cpp
client/parser.cpp
context/kemaisession.cpp
gui/activitydialog.cpp
gui/activitywidget.cpp
gui/autoCompleteComboBox.cpp
gui/customerdialog.cpp
gui/durationedit.cpp
gui/mainwindow.cpp
Expand All @@ -21,31 +23,39 @@ set(SRCS
gui/taskwidget.cpp
main.cpp
misc/datareader.cpp
models/kimaiDataListModel.cpp
models/kimaiDataSortFilterProxyModel.cpp
models/taskfilterproxymodel.cpp
models/tasklistmodel.cpp
monitor/desktopEventsMonitor.cpp
monitor/kimaiEventsMonitor.cpp
settings/settings.cpp
updater/kemaiupdater.cpp)

set(HDRS
client/kimaiapi.h
client/kimaiCache.h
client/kimaiclient.h
client/kimaiclient_p.h
client/kimaireply.h
client/parser.h
context/kemaisession.h
gui/activitydialog.h
gui/activitywidget.h
gui/autoCompleteComboBox.h
gui/customerdialog.h
gui/durationedit.h
gui/mainwindow.h
gui/projectdialog.h
gui/settingsdialog.h
gui/taskwidget.h
misc/datareader.h
models/kimaiDataListModel.h
models/kimaiDataSortFilterProxyModel.h
models/taskfilterproxymodel.h
models/tasklistmodel.h
monitor/desktopEventsMonitor.h
monitor/kimaiEventsMonitor.h
settings/settings.h
updater/kemaiupdater.h
updater/kemaiupdater_p.h)
Expand Down Expand Up @@ -104,7 +114,7 @@ elseif (APPLE)
set(KEMAI_ICNS "${CMAKE_SOURCE_DIR}/bundle/macos/kemai.icns")
set_source_files_properties(${KEMAI_ICNS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/bundle/macos/Info.plist)
target_link_libraries(${PROJECT_NAME} "-framework CoreGraphics")
target_link_libraries(${PROJECT_NAME} range-v3::meta "-framework CoreGraphics")
elseif (UNIX)
list(APPEND SRCS
monitor/linuxDesktopEventsMonitor.cpp)
Expand Down
151 changes: 151 additions & 0 deletions src/client/kimaiCache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include "kimaiCache.h"

/*
* TODO: Removes when std::views is available on MacOS/clang
*/
#ifdef Q_OS_MACOS
# include <range/v3/all.hpp>
#else
# include <ranges>
namespace ranges = std;
#endif

#include <magic_enum.hpp>
#include <spdlog/spdlog.h>

using namespace kemai;

void KimaiCache::synchronize(const std::shared_ptr<KimaiClient>& client, const std::set<Category>& categories)
{
if (!mSyncSemaphore.try_acquire())
{
spdlog::error("Sync already in progress");
return;
}

mStatus = KimaiCache::Status::SyncPending;

// Fill what to sync
if (categories.empty())
{
auto categoryArray = magic_enum::enum_values<Category>();
mPendingSync = {categoryArray.begin(), categoryArray.end()};
}
else
{
mPendingSync = categories;
}

// Notify before running sync requests
emit synchronizeStarted();

for (const auto& category : mPendingSync)
{
switch (category)
{
case Category::Customers: {
mCustomers.clear();
auto customersResult = client->requestCustomers();
connect(customersResult, &KimaiApiBaseResult::ready, this, [this, customersResult] { processCustomersResult(customersResult); });
connect(customersResult, &KimaiApiBaseResult::error, this, [this, customersResult] { processCustomersResult(customersResult); });
}
break;

case Category::Projects: {
mProjects.clear();
auto projectsResult = client->requestProjects();
connect(projectsResult, &KimaiApiBaseResult::ready, this, [this, projectsResult] { processProjectsResult(projectsResult); });
connect(projectsResult, &KimaiApiBaseResult::error, this, [this, projectsResult] { processProjectsResult(projectsResult); });
}
break;

case Category::Activities: {
mActivities.clear();
auto activitiesResult = client->requestActivities();
connect(activitiesResult, &KimaiApiBaseResult::ready, this, [this, activitiesResult] { processActivitiesResult(activitiesResult); });
connect(activitiesResult, &KimaiApiBaseResult::error, this, [this, activitiesResult] { processActivitiesResult(activitiesResult); });
}
break;
}
}
}

KimaiCache::Status KimaiCache::status() const
{
return mStatus;
}

Customers KimaiCache::customers() const
{
return mCustomers;
}

Projects KimaiCache::projects(std::optional<int> customerId) const
{
if (customerId.has_value())
{
auto its = mProjects | ranges::views::filter([id = customerId.value()](auto const& project) { return project.customer.id == id; });
return {its.begin(), its.end()};
}
return mProjects;
}

Activities KimaiCache::activities(std::optional<int> projectId) const
{
if (projectId.has_value())
{
auto its = mActivities | ranges::views::filter([id = projectId.value()](auto const& activity) {
if (!activity.project.has_value())
{
return true;
}
return activity.project->id == id;
});
return {its.begin(), its.end()};
}
return mActivities;
}

void KimaiCache::updateSyncProgress(Category finishedCategory)
{
const std::lock_guard<std::mutex> lockGuard(mProgressMutex);

mPendingSync.erase(finishedCategory);

if (mPendingSync.empty())
{
mStatus = KimaiCache::Status::Ready;
mSyncSemaphore.release();
emit synchronizeFinished();
}
}

void KimaiCache::processCustomersResult(CustomersResult customersResult)
{
if (!customersResult->hasError())
{
mCustomers = customersResult->takeResult();
}
customersResult->deleteLater();
updateSyncProgress(Category::Customers);
}

void KimaiCache::processProjectsResult(ProjectsResult projectsResult)
{
if (!projectsResult->hasError())
{
mProjects = projectsResult->takeResult();
}
projectsResult->deleteLater();
updateSyncProgress(Category::Projects);
}

void KimaiCache::processActivitiesResult(ActivitiesResult activitiesResult)
{
if (!activitiesResult->hasError())
{
mActivities = activitiesResult->takeResult();
}
activitiesResult->deleteLater();
updateSyncProgress(Category::Activities);
}
61 changes: 61 additions & 0 deletions src/client/kimaiCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#include <memory>
#include <mutex>
#include <semaphore>
#include <set>

#include <QObject>

#include "client/kimaiclient.h"

namespace kemai {

class KimaiCache : public QObject
{
Q_OBJECT

public:
enum class Category
{
Customers,
Projects,
Activities
};

enum class Status
{
Empty,
SyncPending,
Ready
};

void synchronize(const std::shared_ptr<KimaiClient>& client, const std::set<Category>& categories = {});
Status status() const;

Customers customers() const;
Projects projects(std::optional<int> customerId = std::nullopt) const;
Activities activities(std::optional<int> projectId = std::nullopt) const;

signals:
void synchronizeStarted();
void synchronizeFinished();

private:
void updateSyncProgress(Category finishedCategory);
void processCustomersResult(CustomersResult customersResult);
void processProjectsResult(ProjectsResult projectsResult);
void processActivitiesResult(ActivitiesResult activitiesResult);

std::set<Category> mPendingSync;

Customers mCustomers;
Projects mProjects;
Activities mActivities;

kemai::KimaiCache::Status mStatus = kemai::KimaiCache::Status::Empty;
std::binary_semaphore mSyncSemaphore{1};
std::mutex mProgressMutex;
};

} // namespace kemai
Loading

0 comments on commit 32a2e9a

Please sign in to comment.