quick commit
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <vector>
|
||||
#include "services/dbus/notification.hpp"
|
||||
#include "services/dbus/mpris.hpp"
|
||||
#include "connection/dbus/notification.hpp"
|
||||
#include "connection/dbus/mpris.hpp"
|
||||
#include "services/notificationController.hpp"
|
||||
#include "services/textureCache.hpp"
|
||||
|
||||
|
||||
0
src/connection/dbus/dbus.cpp
Normal file
0
src/connection/dbus/dbus.cpp
Normal file
@@ -1,4 +1,4 @@
|
||||
#include "services/dbus/mpris.hpp"
|
||||
#include "connection/dbus/mpris.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -19,16 +19,12 @@ std::shared_ptr<MprisController> MprisController::createForPlayer(const std::str
|
||||
}
|
||||
|
||||
MprisController::MprisController() {
|
||||
Gio::DBus::Connection::get(
|
||||
Gio::DBus::BusType::SESSION,
|
||||
sigc::mem_fun(*this, &MprisController::on_bus_connected));
|
||||
connect_session_async(sigc::mem_fun(*this, &MprisController::on_bus_connected));
|
||||
}
|
||||
|
||||
MprisController::MprisController(const std::string &bus_name)
|
||||
: m_player_bus_name(bus_name) {
|
||||
Gio::DBus::Connection::get(
|
||||
Gio::DBus::BusType::SESSION,
|
||||
sigc::mem_fun(*this, &MprisController::on_bus_connected));
|
||||
connect_session_async(sigc::mem_fun(*this, &MprisController::on_bus_connected));
|
||||
}
|
||||
|
||||
std::vector<std::string> MprisController::get_registered_players() const {
|
||||
@@ -65,11 +61,11 @@ void MprisController::on_bus_connected(const Glib::RefPtr<Gio::AsyncResult> &res
|
||||
return;
|
||||
}
|
||||
try {
|
||||
m_connection = Gio::DBus::Connection::get_finish(result);
|
||||
connection = Gio::DBus::Connection::get_finish(result);
|
||||
|
||||
if (!m_dbus_proxy) {
|
||||
m_dbus_proxy = Gio::DBus::Proxy::create_sync(
|
||||
m_connection,
|
||||
connection,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus");
|
||||
@@ -131,10 +127,10 @@ void MprisController::handle_player_registered(const std::string &bus_name) {
|
||||
|
||||
registeredPlayers.insert(bus_name);
|
||||
|
||||
if (bus_name == m_player_bus_name && !m_proxy && m_connection) {
|
||||
if (bus_name == m_player_bus_name && !m_proxy && connection) {
|
||||
try {
|
||||
m_proxy = Gio::DBus::Proxy::create_sync(
|
||||
m_connection,
|
||||
connection,
|
||||
m_player_bus_name,
|
||||
"/org/mpris/MediaPlayer2",
|
||||
"org.mpris.MediaPlayer2.Player");
|
||||
@@ -1,11 +1,9 @@
|
||||
#include "services/dbus/notification.hpp"
|
||||
#include "connection/dbus/notification.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "helpers/string.hpp"
|
||||
#include "services/notificationController.hpp"
|
||||
#include "widgets/notification/copyNotification.hpp"
|
||||
|
||||
#include "glib.h"
|
||||
#include "glibconfig.h"
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "services/tray.hpp"
|
||||
#include "connection/dbus/tray.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
@@ -277,11 +277,7 @@ void TrayService::start() {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Gio::init();
|
||||
} catch (const Glib::Error &) {
|
||||
// Already initialised; ignore.
|
||||
}
|
||||
ensure_gio_init();
|
||||
|
||||
if (!nodeInfo) {
|
||||
try {
|
||||
119
src/connection/httpConnection.cpp
Normal file
119
src/connection/httpConnection.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "connection/httpConnection.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace {
|
||||
size_t write_to_string(void *contents, size_t size, size_t nmemb, void *userp) {
|
||||
size_t total = size * nmemb;
|
||||
auto *buffer = static_cast<std::string *>(userp);
|
||||
buffer->append(static_cast<char *>(contents), total);
|
||||
return total;
|
||||
}
|
||||
|
||||
std::string trim(std::string value) {
|
||||
auto not_space = [](unsigned char c) { return std::isspace(c) == 0; };
|
||||
value.erase(value.begin(),
|
||||
std::find_if(value.begin(), value.end(), not_space));
|
||||
value.erase(std::find_if(value.rbegin(), value.rend(), not_space).base(),
|
||||
value.end());
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t header_to_map(char *buffer, size_t size, size_t nitems, void *userdata) {
|
||||
size_t total = size * nitems;
|
||||
auto *header_map = static_cast<std::map<std::string, std::string> *>(userdata);
|
||||
|
||||
std::string line(buffer, total);
|
||||
auto colon = line.find(':');
|
||||
if (colon != std::string::npos) {
|
||||
auto key = trim(line.substr(0, colon));
|
||||
auto value = trim(line.substr(colon + 1));
|
||||
if (!key.empty()) {
|
||||
header_map->insert_or_assign(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
HttpResponse HttpConnection::get(const std::string &url,
|
||||
const std::map<std::string, std::string> &headers,
|
||||
long timeout_ms) {
|
||||
return performRequest("GET", url, std::string(), headers, std::string(), timeout_ms);
|
||||
}
|
||||
|
||||
HttpResponse HttpConnection::post(const std::string &url,
|
||||
const std::string &body,
|
||||
const std::map<std::string, std::string> &headers,
|
||||
const std::string &content_type,
|
||||
long timeout_ms) {
|
||||
return performRequest("POST", url, body, headers, content_type, timeout_ms);
|
||||
}
|
||||
|
||||
HttpResponse HttpConnection::performRequest(const std::string &method,
|
||||
const std::string &url,
|
||||
const std::string &body,
|
||||
const std::map<std::string, std::string> &headers,
|
||||
const std::string &content_type,
|
||||
long timeout_ms) {
|
||||
HttpResponse response;
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
response.error = "curl_easy_init failed";
|
||||
return response;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response.body);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_to_map);
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response.headers);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "bar/1.0");
|
||||
|
||||
if (timeout_ms > 0) {
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_ms);
|
||||
}
|
||||
|
||||
if (method == "POST") {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
|
||||
} else {
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
|
||||
}
|
||||
|
||||
struct curl_slist *header_list = nullptr;
|
||||
for (const auto &pair : headers) {
|
||||
std::string header = pair.first + ": " + pair.second;
|
||||
header_list = curl_slist_append(header_list, header.c_str());
|
||||
}
|
||||
|
||||
if (method == "POST" && !content_type.empty()) {
|
||||
std::string content_header = "Content-Type: " + content_type;
|
||||
header_list = curl_slist_append(header_list, content_header.c_str());
|
||||
}
|
||||
|
||||
if (header_list) {
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
|
||||
}
|
||||
|
||||
auto result = curl_easy_perform(curl);
|
||||
if (result != CURLE_OK) {
|
||||
response.error = curl_easy_strerror(result);
|
||||
}
|
||||
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response.status_code);
|
||||
|
||||
if (header_list) {
|
||||
curl_slist_free_all(header_list);
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "services/dbus/messages.hpp"
|
||||
#include "connection/dbus/messages.hpp"
|
||||
#include "widgets/notification/baseNotification.hpp"
|
||||
#include "widgets/notification/copyNotification.hpp"
|
||||
#include "widgets/notification/notificationWindow.hpp"
|
||||
|
||||
@@ -34,10 +34,8 @@ ControlCenter::ControlCenter(std::string icon, std::string name)
|
||||
this->controlCenterContainer.set_orientation(Gtk::Orientation::VERTICAL);
|
||||
this->controlCenterContainer.set_spacing(4);
|
||||
|
||||
this->testLabel.set_text("Test tab");
|
||||
|
||||
this->contentStack.add(this->controlCenterContainer, "controls", "Controls");
|
||||
this->contentStack.add(this->testLabel, "test", "Test");
|
||||
this->contentStack.add(this->weatherWidget, "test", "Test");
|
||||
this->contentStack.set_visible_child("controls");
|
||||
this->setActiveTab("controls");
|
||||
|
||||
|
||||
112
src/widgets/weather.cpp
Normal file
112
src/widgets/weather.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "widgets/weather.hpp"
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <glibmm/main.h>
|
||||
#include <ios>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
constexpr const char *kWeatherUrl =
|
||||
"https://api.open-meteo.com/v1/forecast?latitude=49.0094&longitude=8.4044&daily=temperature_2m_max,temperature_2m_min,weather_code&hourly=temperature_2m,rain¤t=temperature_2m&timezone=Europe%2FBerlin";
|
||||
|
||||
size_t write_to_buffer(void *contents, size_t size, size_t nmemb, void *userp) {
|
||||
size_t total = size * nmemb;
|
||||
auto *buffer = static_cast<std::string *>(userp);
|
||||
buffer->append(static_cast<char *>(contents), total);
|
||||
return total;
|
||||
}
|
||||
|
||||
std::string formatTemp(double value) {
|
||||
std::ostringstream ss;
|
||||
ss.setf(std::ios::fixed);
|
||||
ss.precision(1);
|
||||
ss << value << "°C";
|
||||
return ss.str();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
WeatherWidget::WeatherWidget()
|
||||
: Gtk::Box(Gtk::Orientation::VERTICAL) {
|
||||
this->set_orientation(Gtk::Orientation::VERTICAL);
|
||||
this->set_spacing(6);
|
||||
this->set_margin_top(4);
|
||||
this->set_margin_bottom(4);
|
||||
this->set_margin_start(4);
|
||||
this->set_margin_end(4);
|
||||
|
||||
this->titleLabel.set_text("Weather");
|
||||
this->currentLabel.set_text("Now: --");
|
||||
this->todayLabel.set_text("Today: -- / --");
|
||||
|
||||
this->append(this->titleLabel);
|
||||
this->append(this->currentLabel);
|
||||
this->append(this->todayLabel);
|
||||
|
||||
this->fetchWeather();
|
||||
Glib::signal_timeout().connect_seconds(
|
||||
sigc::mem_fun(*this, &WeatherWidget::onRefreshTick),
|
||||
3600);
|
||||
}
|
||||
|
||||
bool WeatherWidget::onRefreshTick() {
|
||||
this->fetchWeather();
|
||||
return true;
|
||||
}
|
||||
|
||||
void WeatherWidget::fetchWeather() {
|
||||
std::thread([this]() {
|
||||
std::string buffer;
|
||||
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
Glib::signal_idle().connect_once([this]() {
|
||||
this->applyWeatherText("Now: --", "Today: -- / --");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, kWeatherUrl);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_buffer);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "bar/1.0");
|
||||
|
||||
auto res = curl_easy_perform(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res != CURLE_OK || buffer.empty()) {
|
||||
Glib::signal_idle().connect_once([this]() {
|
||||
this->applyWeatherText("Now: --", "Today: -- / --");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
auto json = nlohmann::json::parse(buffer);
|
||||
double current = json.at("current").at("temperature_2m").get<double>();
|
||||
double minTemp = json.at("daily").at("temperature_2m_min").at(0).get<double>();
|
||||
double maxTemp = json.at("daily").at("temperature_2m_max").at(0).get<double>();
|
||||
|
||||
std::string currentText = "Now: " + formatTemp(current);
|
||||
std::string todayText = "Today: " + formatTemp(minTemp) + " / " + formatTemp(maxTemp);
|
||||
|
||||
Glib::signal_idle().connect_once([this, currentText, todayText]() {
|
||||
this->applyWeatherText(currentText, todayText);
|
||||
});
|
||||
} catch (const std::exception &ex) {
|
||||
spdlog::error("Weather parse error: {}", ex.what());
|
||||
Glib::signal_idle().connect_once([this]() {
|
||||
this->applyWeatherText("Now: --", "Today: -- / --");
|
||||
});
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void WeatherWidget::applyWeatherText(const std::string ¤t_text,
|
||||
const std::string &today_text) {
|
||||
this->currentLabel.set_text(current_text);
|
||||
this->todayLabel.set_text(today_text);
|
||||
}
|
||||
Reference in New Issue
Block a user