Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## 2025.5.1
### Breaking Changes
#### System
- A Process' status can now be queued with `Process::getState()` which returns a `ProcessState` value
### New APIs
#### Localizationm
- Added `_f()` macro for creating strings with translated format strings
- Added `Gettext::getAvailableLanguages()` function
#### System
- Added `ProcessState` enum
- Added `Process::pause()` method
- Added `Process::resume()` method
### Fixes
None

## 2025.5.0
### Breaking Changes
#### Notifications
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")

#libnick Definition
project ("libnick" LANGUAGES C CXX VERSION 2025.5.0 DESCRIPTION "A cross-platform base for native Nickvision applications.")
project ("libnick" LANGUAGES C CXX VERSION 2025.5.1 DESCRIPTION "A cross-platform base for native Nickvision applications.")
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
include(CTest)
Expand Down Expand Up @@ -157,6 +157,7 @@ if (BUILD_TESTING)
"tests/hardwaretests.cpp"
"tests/ipctests.cpp"
"tests/keyringtests.cpp"
"tests/localizationtests.cpp"
"tests/loggingtests.cpp"
"tests/main.cpp"
"tests/networktests.cpp"
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = "libnick"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = "2025.3.6"
PROJECT_NUMBER = "2025.5.1"

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
24 changes: 22 additions & 2 deletions include/localization/gettext.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,23 @@
#ifndef GETTEXT_H
#define GETTEXT_H

#include <format>
#include <string>
#include <vector>
#include <libintl.h>

#define GETTEXT_CONTEXT_SEPARATOR "\004"
#define _(String) dgettext(::Nickvision::Localization::Gettext::getDomainName().c_str(), String)
#define _n(String, StringPlural, N) dngettext(::Nickvision::Localization::Gettext::getDomainName().c_str(), String, StringPlural, static_cast<unsigned long>(N))
#define _f(String, ...) ::Nickvision::Localization::Gettext::fgettext(String, __VA_ARGS__)
#define _p(Context, String) ::Nickvision::Localization::Gettext::pgettext(Context GETTEXT_CONTEXT_SEPARATOR String, String)
#define _pn(Context, String, StringPlural, N) ::Nickvision::Localization::Gettext::pngettext(Context GETTEXT_CONTEXT_SEPARATOR String, String, StringPlural, static_cast<unsigned long>(N))

namespace Nickvision::Localization::Gettext
{
/**
* @brief Initializes the gettext system. This function should only be called once, regardless of with different domain names.
* @param domainName The domain name to use for gettext translations. Must be lowercase and contain no spaces.
* @param domainName The domain name to use for gettext translations. Must be lowercase and contain no spaces
* @return True if initialized, else false
*/
bool init(const std::string& domainName);
Expand All @@ -45,6 +48,23 @@ namespace Nickvision::Localization::Gettext
* @return The gettext domain name
*/
const std::string& getDomainName();
/**
* @brief Gets the list of available translated languages.
* @return The list of available translated languages.
*/
const std::vector<std::string>& getAvailableLanguages();
/**
* @brief Translates a message and formats it with the given arguments.
* @param msg The message to translate
* @param args The arguments to format the translated message with
*/
template<typename... Args>
const char* fgettext(const char* msg, Args&&... args)
{
static std::string res;
res = std::vformat(_(msg), std::make_format_args(args...));
return res.c_str();
}
/**
* @brief Translates a message for a given context.
* @param context The context of the message
Expand All @@ -63,4 +83,4 @@ namespace Nickvision::Localization::Gettext
const char* pngettext(const char* context, const char* msg, const char* msgPlural, unsigned long n);
}

#endif //GETTEXT_H
#endif //GETTEXT_H
48 changes: 27 additions & 21 deletions include/system/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <vector>
#include "events/event.h"
#include "processexitedeventargs.h"
#include "processstate.h"
#ifdef _WIN32
#include <windows.h>
#else
Expand Down Expand Up @@ -59,26 +60,21 @@ namespace Nickvision::System
* @brief This method will wait for the process to exit if it is still running.
*/
~Process();
/**
* @brief Gets the path of the process.
* @return The path of the process
*/
const std::filesystem::path& getPath() const;
/**
* @brief Gets the event for when the process has exited.
* @return The process exited event
*/
Events::Event<ProcessExitedEventArgs>& exited();
/**
* @brief Gets whether or not the process is running.
* @return True if running, else false
* @brief Gets the path of the process.
* @return The path of the process
*/
bool isRunning() const;
const std::filesystem::path& getPath() const;
/**
* @brief Gets whether or not the process has completed.
* @return True if completed, else false
* @brief Gets the state of the proicess.
* @return The state of the process.
*/
bool hasCompleted() const;
ProcessState getState() const;
/**
* @brief Gets the exit code of the process.
* @return The exit code of the process. -1 if the process has not completed
Expand All @@ -89,18 +85,19 @@ namespace Nickvision::System
* @return The console output of the process. Empty if the process has not completed
*/
const std::string& getOutput() const;
/**
* @brief Gets the amount of RAM being used by the process in bytes.
* @return The amount of RAM used by the process
*/
unsigned long long getRAMUsage() const;
/**
* @brief Gets the percent of the CPU being used by the process.
* @return The CPU usage of the process
*/
double getCPUUsage() const;
/**
* @brief Gets the amount of RAM being used by the process in bytes.
* @return The amount of RAM used by the process
*/
unsigned long long getRAMUsage() const;
/**
* @brief Starts the process.
* @brief Use Process::resume() to start again a paused process.
* @return True if the process was started, else false
*/
bool start();
Expand All @@ -109,21 +106,31 @@ namespace Nickvision::System
* @return True if the process was killed, else false
*/
bool kill();
/**
* @brief Resumes the process.
* @return True if the process was resumed, else false
*/
bool resume();
/**
* @brief Pauses the process.
* @return True if the process was paused, else false
*/
bool pause();
/**
* @brief Waits for the process to exit.
* @brief This function will block until the process has exited.
* @brief Make sure to call start() before calling this function.
* @brief Make sure to call start() / resume() before calling this function.
* @return The exit code of the process
*/
int waitForExit();
/**
* @brief Send text to the process's console.
* @brief Sends text to the process' console.
* @param s The text to send
* @return True if the text is sent, else false
*/
bool send(const std::string& s);
/**
* @brief Send text to the process's console and adds the return characters.
* @brief Sends text to the process' console and adds the return characters.
* @param s The command to send
* @return True if the command is sent, else false
*/
Expand All @@ -139,8 +146,7 @@ namespace Nickvision::System
std::vector<std::string> m_args;
std::filesystem::path m_workingDirectory;
Events::Event<ProcessExitedEventArgs> m_exited;
bool m_running;
bool m_completed;
ProcessState m_state;
int m_exitCode;
std::string m_output;
std::thread m_watchThread;
Expand Down
19 changes: 19 additions & 0 deletions include/system/processstate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#ifndef PROCESSSTATE_H
#define PROCESSSTATE_H

namespace Nickvision::System
{
/**
* @brief States of a process.
*/
enum class ProcessState
{
Created, //The process was just created (start() not yet called)
Running, //The process is running
Killed, //The process was killed and is no longer running
Paused, //The process was paused and is no longer running (continue using resume())
Completed //The process was completed and is no longer running
};
}

#endif //PROCESSSTATE_H
15 changes: 11 additions & 4 deletions manual/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@

libnick provides Nickvision apps with a common set of cross-platform APIs for managing system and desktop app functionality such as network management, taskbar icons, translations, app updates, and more.

## 2025.3.6
## 2025.5.1
### Breaking Changes
None
#### System
- A Process' status can now be queued with `Process::getState()` which returns a `ProcessState` value
### New APIs
None
#### Localizationm
- Added `_f()` macro for creating strings with translated format strings
- Added `Gettext::getAvailableLanguages()` function
#### System
- Added `ProcessState` enum
- Added `Process::pause()` method
- Added `Process::resume()` method
### Fixes
- Library linking on Windows
None

## Dependencies
The following are a list of dependencies used by libnick.
Expand Down
4 changes: 2 additions & 2 deletions src/filesystem/filesystemwatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ namespace Nickvision::Filesystem
{
return;
}
OVERLAPPED overlapped{ 0 };
OVERLAPPED overlapped{};
overlapped.hEvent = CreateEvent(nullptr, 1, 0, nullptr);
if (!overlapped.hEvent)
{
Expand Down Expand Up @@ -312,4 +312,4 @@ namespace Nickvision::Filesystem
}
}
#endif
}
}
22 changes: 5 additions & 17 deletions src/localization/documentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,16 @@ namespace Nickvision::Localization
#endif
if (!sysLocale.empty() && sysLocale != "C" && sysLocale != "en_US" && sysLocale != "*")
{
/*
* Because the translations of a Nickvision application are stored in the application's running
* directory, we can look at the list of directory names and see if they contain a translation
* file (.mo) for the sysLocale string. If a directory contains an mo file, we can set the
* documentation lang to the sysLocale. If no directory contains an mo file for the sysLocale,
* we can try to match using the two-letter language code. If that doesn't work, the default
* English docs will be used.
*/
std::string twoLetter{ StringHelpers::split(sysLocale, "_")[0] };
for (const std::filesystem::directory_entry& e : std::filesystem::directory_iterator(Environment::getExecutableDirectory()))
for(const std::string& l : Gettext::getAvailableLanguages())
{
if (e.is_directory() && std::filesystem::exists(e.path() / (Gettext::getDomainName() + ".mo")))
if(l == sysLocale || l == twoLetter)
{
std::string l{ e.path().filename().string() };
if(l == sysLocale || l == twoLetter)
{
lang = l;
break;
}
lang = l;
break;
}
}
}
return "https://htmlpreview.github.io/?" + htmlDocStore + "/" + lang + "/" + pageName + ".html";
}
}
}
20 changes: 18 additions & 2 deletions src/localization/gettext.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "localization/gettext.h"
#include <filesystem>
#include <cstdlib>
#include <filesystem>
#include "helpers/stringhelpers.h"
#include "system/environment.h"

Expand Down Expand Up @@ -37,6 +37,22 @@ namespace Nickvision::Localization
return s_domainName;
}

const std::vector<std::string>& Gettext::getAvailableLanguages()
{
static std::vector<std::string> langs;
if(langs.empty())
{
for (const std::filesystem::directory_entry& e : std::filesystem::directory_iterator(Environment::getExecutableDirectory()))
{
if (e.is_directory() && std::filesystem::exists(e.path() / (getDomainName() + ".mo")))
{
langs.push_back(e.path().filename().string());
}
}
}
return langs;
}

const char* Gettext::pgettext(const char* context, const char* msg)
{
const char* translation{ dcgettext(s_domainName.c_str(), context, LC_MESSAGES) };
Expand All @@ -56,4 +72,4 @@ namespace Nickvision::Localization
}
return translation;
}
}
}
4 changes: 2 additions & 2 deletions src/system/hardwareinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Nickvision::System
unsigned long long HardwareInfo::getTotalRamSize()
{
#ifdef _WIN32
MEMORYSTATUSEX status;
MEMORYSTATUSEX status{};
status.dwLength = sizeof(status);
if(GlobalMemoryStatusEx(&status))
{
Expand Down Expand Up @@ -53,7 +53,7 @@ namespace Nickvision::System
unsigned long long HardwareInfo::getFreeRamSize()
{
#ifdef _WIN32
MEMORYSTATUSEX status;
MEMORYSTATUSEX status{};
status.dwLength = sizeof(status);
if(GlobalMemoryStatusEx(&status))
{
Expand Down
Loading
Loading