From 80ee3fcadf5e1b77fa976a8e69ce450ddfbe38d9 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Mon, 24 Nov 2025 14:52:17 +0100 Subject: [PATCH 1/6] Many changes to setup colours, update window positions, put notes on desktop, etc. Signed-off-by: Hans Dijkema --- CMakeLists.txt | 4 +- Makefile | 19 ++ gtk-imports.h | 18 +- gtkloader.cpp | 1 + main.cpp | 4 + to_desktop.png | Bin 0 -> 16264 bytes to_desktop.svg | 4 + yellownotes.cpp | 560 +++++++++++++++++++++++++++++++++++++----------- yellownotes.h | 14 ++ 9 files changed, 493 insertions(+), 131 deletions(-) create mode 100644 Makefile create mode 100644 to_desktop.png create mode 100644 to_desktop.svg diff --git a/CMakeLists.txt b/CMakeLists.txt index fa0b7bd..70e02c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,9 @@ add_executable(yellownotes main.cpp gtkloader.h gtkloader.cpp gtk-imports.c yellownotes.h yellownotes.cpp - tr.h tr.cpp) + tr.h tr.cpp + utils/whereami.c utils/whereami.h + exe_path.h exe_path.cpp) include(GNUInstallDirs) install(TARGETS yellownotes diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f64453d --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ + + +all: release + @echo make install + +install: release + mkdir -p /opt/yellownotes + cp build/release/yellownotes *.svg *.png /opt/yellownotes + +release: build/release/yellownotes + +build/release/yellownotes: exe_path.cpp gtk-imports.c gtkloader.cpp main.cpp tr.cpp yellownotes.cpp utils/whereami.c \ + exe_path.h gtk-imports.h gtkloader.h tr.h yellownotes.h utils/whereami.h + cmake -S . -B build/release + cmake --build build/release --target all + + +clean: + rm -rf build/release diff --git a/gtk-imports.h b/gtk-imports.h index 0282eb8..42b686e 100644 --- a/gtk-imports.h +++ b/gtk-imports.h @@ -1,6 +1,8 @@ #ifndef GTK_IMPORTS_H #define GTK_IMPORTS_H +#include + /************************************************************************************* * boiler plate code to initialize Gtk functions etc. *************************************************************************************/ @@ -68,13 +70,16 @@ typedef void GtkDialog; typedef void GTimer; typedef void GtkComboBoxText; typedef void GtkComboBox; +typedef void GtkGrid; +typedef void GtkColorButton; +typedef void GtkColorChooser; typedef int gboolean; typedef int gint; typedef char gchar; typedef long glong; typedef unsigned long gulong; -typedef unsigned long guint32; +typedef unsigned int guint32; typedef unsigned int guint; typedef long long gint64; typedef unsigned long long guint64; @@ -274,7 +279,7 @@ typedef struct _GdkEventMotion gint16 is_hint; GdkDevice *device; gdouble x_root, y_root; -} GdkEventMotion; +} GdkEventMotion;; typedef struct _GdkEventKey { @@ -649,11 +654,20 @@ DECL(void, gtk_widget_set_vexpand, (GtkWidget* widget, gboolean expand )) DECL(void, gtk_widget_set_hexpand, (GtkWidget* widget, gboolean expand )) DECL(void, gtk_widget_set_halign, (GtkWidget* widget, GtkAlign align )) DECL(void, gtk_widget_set_valign, (GtkWidget* widget, GtkAlign align )) +DECL(GtkWidget*,gtk_grid_new, (void)) +DECL(void, gtk_grid_attach, (GtkGrid* grid, GtkWidget* child, gint left, gint top, gint width, gint height )) + +DECL(GtkWidget*, gtk_color_button_new, (void )) +DECL(void, gtk_color_chooser_set_rgba, (GtkColorChooser* chooser, const GdkRGBA* color )) +DECL(void, gtk_color_chooser_get_rgba, (GtkColorChooser* chooser, GdkRGBA* color )) DECL(gboolean, gtk_widget_translate_coordinates, ( GtkWidget* src_widget, GtkWidget* dest_widget, gint src_x, gint src_y, gint* dest_x, gint* dest_y)) DECL(void, gtk_main, (void)) DECL(void, gtk_main_quit, (void)) +DECL(GdkEvent*, gtk_get_current_event, (void )) +DECL(void, gtk_main_do_event, (GdkEvent* event)) +DECL(void, gdk_event_free, (GdkEvent* event)) DECL(unsigned long, g_signal_connect_data, (GObject *obj, const char *signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags)) diff --git a/gtkloader.cpp b/gtkloader.cpp index 21edad6..6685ef7 100644 --- a/gtkloader.cpp +++ b/gtkloader.cpp @@ -123,6 +123,7 @@ void GtkLoader::dlopen() "libgio-2.0.so", "libglib-2.0.so", "libgdk-3.so", + "libgdk_pixbuf-2.0.so", NULL }; int i; diff --git a/main.cpp b/main.cpp index 9e88434..e9906c9 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ extern "C" { } #include "yellownotes.h" +#include "exe_path.h" SIGNAL(YellowNotes, on_tray_activate, popupTrayMenu) @@ -22,9 +23,12 @@ static void activate (GtkApplication* app, gpointer user_data) int main(int argc, char **argv) { GtkLoader l; + WhereAmI w; srand(time(NULL)); // seed with current time + std::string my_path = w.containing_folder(); + try { l.loadGtk(); } catch(std::string msg) { diff --git a/to_desktop.png b/to_desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..35b5a1eefd2627d3f337cfeeb021bd661206fa59 GIT binary patch literal 16264 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
{znIbS`;9uutR5BOJdwAo{f9<=-_0h!MY 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 + + + \ No newline at end of file diff --git a/yellownotes.cpp b/yellownotes.cpp index e055c33..f83721c 100644 --- a/yellownotes.cpp +++ b/yellownotes.cpp @@ -22,6 +22,8 @@ extern "C" { #include "tr.h" +#include + static void trim(std::string &s) { size_t start = s.find_first_not_of(" \t\n\r"); size_t end = s.find_last_not_of(" \t\n\r"); @@ -49,6 +51,7 @@ private: GtkImage *_delete_image; GtkImage *_plus_image; GtkImage *_hide_image; + GtkImage *_to_desktop_image; GtkWidget *_title_label; GtkWidget *_title_entry; GtkWidget *_title_separator; @@ -62,16 +65,24 @@ private: std::string _title; bool _hidden; + bool _hidden_loaded; + int _x; int _y; + bool _pos_loaded; + int _width; int _height; + bool _size_loaded; + bool _in_transaction; bool _editing_title; int _save_counter; int _save_id; + bool _double_clicked; + ColorType_t _color; bool _color_changed; @@ -106,11 +117,14 @@ private: void updateWidgetColors(GtkWidget *w); public: - void changed(GtkWidget *sender); - void size_allocated(GtkWidget *sender, GtkAllocation *a); + void resized(int width, int height); + void size_allocated(GtkWidget *sender, GtkAllocation *alloc); + void positioned(GtkWidget *sender, int x, int y); public: void toFront(); + void toDesktop(); + void fromDesktop(); public: bool move_begin(GtkWidget *sender, GdkEventButton *evt); @@ -127,6 +141,7 @@ public: public: std::string title(); bool isHidden(); + void doubleClicked(); public: void load(); @@ -137,6 +152,34 @@ public: ~YellowNote(); }; +class ColorSet +{ +public: + ColorType_t color; + YellowNotes *notes; + bool bg; + +public: + void colorSet(GtkColorButton *sender) { + GdkRGBA rgba; + gtk_color_chooser_get_rgba(sender, &rgba); + std::string c = notes->fromRGBA(rgba); + if (bg) { + notes->setBgColor(color, c); + } else { + notes->setFgColor(color, c); + } + } + + ColorSet(ColorType_t t, bool _bg, YellowNotes *n) { + color = t; + bg = _bg; + notes = n; + } +}; + +SIGNAL(ColorSet, on_color_set, colorSet); + SIGNAL2(YellowNote, on_size_allocated, size_allocated, GtkAllocation) BSIGNAL2(YellowNote, on_button_press, move_begin, GdkEventButton); BSIGNAL2(YellowNote, on_button_release, move_end, GdkEventButton); @@ -156,7 +199,8 @@ static gboolean on_text_save_timeout(gpointer data) } SIGNAL(YellowNotes, on_new_yellow, newNote) -SIGNAL(YellowNotes, on_show, showNotes); +SIGNAL(YellowNotes, on_show, notesFromDesktop); +SIGNAL(YellowNotes, on_to_back, notesToDesktop); SIGNAL(YellowNotes, on_reload, reloadNotes); SIGNAL(YellowNotes, on_setup, setup); SIGNAL(YellowNotes, on_quit, quit) @@ -210,28 +254,108 @@ std::string YellowNotes::notesDir() return notes_dir; } -std::string YellowNotes::css(ColorType_t type) +std::string YellowNotes::fromRGBA(const GdkRGBA &rgba) { - const char *bgs[] = { "#404040", // dark - "#faf32a", // yellow - "#fcbf56", // orange, - "#5df0f5", // blue - "#fc77f4", // Cyaan - "#74fc94", // greeen - "#f7bcbc", // red - "#cdcfd1" // grey + char buf[100]; + + auto to255 = [](double c) { + return static_cast(floor((c * 255) + 0.5)); }; - const char *fgs[] = { "white", - "black", - "black", - "black", - "black", - "black", - "black", - "black" + sprintf(buf, "#%02x%02x%02x", to255(rgba.red), to255(rgba.green), to255(rgba.blue)); + std::string col = buf; + return col; +} + +void YellowNotes::toRGBA(const std::string &col, GdkRGBA &rgba) +{ + auto from_hex = [](std::string hex_num) { + return strtol(hex_num.c_str(), NULL, 16); }; + double red = from_hex(col.substr(1, 2)) / 255.0; + double green = from_hex(col.substr(3, 2)) / 255.0; + double blue = from_hex(col.substr(5, 2)) / 255.0; + double alpha = 1.0; + + rgba.alpha = alpha; + rgba.blue = blue; + rgba.green = green; + rgba.red = red; +} + +std::string YellowNotes::getFgColor(ColorType_t type) +{ + char buf[100]; + sprintf(buf, "fg_color_%d", type); + std::string key = buf; + std::unordered_map::iterator it = _cfg.find(key); + if (it != _cfg.end()) { + return _cfg[key]; + } else { + const char *fgs[] = { "#ffffff", + "#000000", + "#000000", + "#000000", + "#000000", + "#000000", + "#000000", + "#000000" + }; + std::string c(fgs[type]); + return c; + } +} + +std::string YellowNotes::getBgColor(ColorType_t type) +{ + char buf[100]; + sprintf(buf, "bg_color_%d", type); + std::string key = buf; + std::unordered_map::iterator it = _cfg.find(key); + if (it != _cfg.end()) { + return _cfg[key]; + } else { + const char *bgs[] = { + "#404040", // dark + "#faf32a", // yellow + "#fcbf56", // orange, + "#5df0f5", // blue + "#fc77f4", // Cyaan + "#74fc94", // greeen + "#f7bcbc", // red + "#cdcfd1" // grey + }; + std::string c(bgs[type]); + return c; + } +} + +void YellowNotes::setFgColor(ColorType_t type, const std::string &col) +{ + char buf[100]; + sprintf(buf, "fg_color_%d", type); + std::string key = buf; + _cfg.erase(key); + _cfg.insert(std::pair(key, col)); + saveConfig(); +} + +void YellowNotes::setBgColor(ColorType_t type, const std::string &col) +{ + char buf[100]; + sprintf(buf, "bg_color_%d", type); + std::string key = buf; + _cfg.erase(key); + _cfg.insert(std::pair(key, col)); + saveConfig(); +} + +std::string YellowNotes::css(ColorType_t type) +{ + + if (type > LAST) { type = YELLOW; } + auto from_hex = [](std::string hex_num) { return strtol(hex_num.c_str(), NULL, 16); }; @@ -255,14 +379,14 @@ std::string YellowNotes::css(ColorType_t type) std::string css = std::string() + "label, box.horizontal, textview.view, textview.view text, frame, messagedialog.background {\n" - " background-color: " + bgs[type] + ";\n" - " color: " + fgs[type] + ";\n" + " background-color: " + getBgColor(type) + ";\n" + " color: " + getFgColor(type) + ";\n" " font-family: sans;\n" " font-size: " + font_size + ";\n" "}\n" "frame border {\n" " border: none;\n" - " box-shadow: 5px 5px 5px " + darker(bgs[type]) + ";\n" + " box-shadow: 5px 5px 5px " + darker(getBgColor(type)) + ";\n" " margin: 5px;\n" "}\n"; @@ -291,6 +415,7 @@ void YellowNotes::popupTrayMenu(void *sender) GtkMenuItem *new_yellow = gtk_menu_item_new_with_label(_("New Note")); GtkMenuItem *show_notes = gtk_menu_item_new_with_label(_("Show Notes")); + GtkMenuItem *notes_to_back = gtk_menu_item_new_with_label(_("Notes on desktop")); GtkMenuItem *reload_notes = gtk_menu_item_new_with_label(_("Reload Notes")); GtkWidget *sep = gtk_separator_menu_item_new(); @@ -314,6 +439,7 @@ void YellowNotes::popupTrayMenu(void *sender) gtk_menu_shell_append(tray_menu, new_yellow); gtk_menu_shell_append(tray_menu, show_notes); + gtk_menu_shell_append(tray_menu, notes_to_back); gtk_menu_shell_append(tray_menu, reload_notes); gtk_menu_shell_append(tray_menu, sep); @@ -330,6 +456,7 @@ void YellowNotes::popupTrayMenu(void *sender) g_signal_connect(new_yellow, "activate", on_new_yellow, this); g_signal_connect(show_notes, "activate", on_show, this); + g_signal_connect(notes_to_back, "activate", on_to_back, this); g_signal_connect(reload_notes, "activate", on_reload, this); g_signal_connect(setup, "activate", on_setup, this); g_signal_connect(quit, "activate", on_quit, this); @@ -393,6 +520,7 @@ void YellowNotes::loadConfig() } setLang(currentLang()); + } void YellowNotes::saveConfig() @@ -412,6 +540,13 @@ void YellowNotes::saveConfig() } } +gboolean load_notes_timeout(void *_notes) +{ + YellowNotes *notes = static_cast(_notes); + notes->notesToDesktop(nullptr); + return false; +} + void YellowNotes::loadNotes() { gtk_widget_show_all(topLevel()); @@ -437,12 +572,17 @@ void YellowNotes::loadNotes() const auto base_name = entry.path().filename().string(); if (base_name.rfind(".note") > 0) { YellowNote *note = new YellowNote(this, full_name); + //note->fromDesktop(); _notes.push_back(note); } } } gtk_widget_hide(topLevel()); + + if (cfgOnDesktop()) { + g_timeout_add(500, load_notes_timeout, this); + } } void YellowNotes::showNotes(void *sender) @@ -453,7 +593,27 @@ void YellowNotes::showNotes(void *sender) note->toFront(); it++; } +} +void YellowNotes::notesToDesktop(void *sender) +{ + std::list::const_iterator it = _notes.begin(); + while (it != _notes.end()) { + YellowNote *note = *it; + note->toDesktop(); + it++; + } + setCfgOnDesktop(true); +} + +void YellowNotes::notesFromDesktop(void *sender) +{ std::list::const_iterator it = _notes.begin(); + while (it != _notes.end()) { + YellowNote *note = *it; + note->fromDesktop(); + it++; + } + setCfgOnDesktop(false); } void YellowNotes::setupCancel(GtkWidget *sender) @@ -474,17 +634,22 @@ bool YellowNotes::setupDel(GtkWidget *sender, void *evt) void YellowNotes::setupClose(GtkWidget *sender) { if (_dlg != nullptr) { - std::cout << "hey" << std::endl; gtk_dialog_response(_dlg, GTK_RESPONSE_OK); std::string lang = std::string(gtk_combo_box_get_active_id(_langs)); - std::cout << "lang " << lang << std::endl; setCurrentLang(lang); gtk_widget_destroy(_dlg); + + std::list::iterator it; + for(it = _color_sets.begin() ; it != _color_sets.end(); it++) { + ColorSet *s = *it; + delete s; + } + _color_sets.clear(); + _dlg = nullptr; _langs = nullptr; saveConfig(); } else { - std::cout << "close button" << std::endl; } } @@ -504,13 +669,55 @@ void YellowNotes::setup(void *sender) gtk_combo_box_text_append(langs, "en", "English"); gtk_combo_box_text_append(langs, "nl", "Nederlands"); + GtkWidget *lbl_langs = gtk_label_new(_("Language:")); + gtk_widget_set_size_request(lbl_langs, 150, -1); + std::string current_lang = currentLang(); gtk_combo_box_set_active_id(langs, current_lang.c_str()); + gtk_widget_set_size_request(langs, 300, -1); - GtkWidget *hbox = gtk_box_new(GtkOrientation::GTK_ORIENTATION_HORIZONTAL, 5); + GtkGrid *grid = gtk_grid_new(); - gtk_container_add(hbox, langs); - gtk_container_add(content, hbox); + gtk_grid_attach(grid, lbl_langs, 0, 0, 1, 1); + gtk_grid_attach(grid, langs, 1, 0, 2, 1); + + GtkLabel *lbl_fg = gtk_label_new(_("Forground Color")); + GtkLabel *lbl_bg = gtk_label_new(_("Background Color")); + gtk_grid_attach(grid, lbl_fg, 1, 1, 1, 1); + gtk_grid_attach(grid, lbl_bg, 2, 1, 1, 1); + + + int i = ColorType_t::FIRST; + std::string colors[] = { _("Dark"), _("Yellow"), _("Orange"), + _("Blue"), _("Cyan"), _("Green"), _("Red"), _("Grey") }; + + int offset = 2; + + for(;i <= ColorType_t::LAST; i++) { + GtkWidget *lbl = gtk_label_new(colors[i].c_str()); + gtk_grid_attach(grid, lbl, 0, i + offset, 1, 1); + + GdkRGBA bg_rgba, fg_rgba; + std::string fg_color = getFgColor(static_cast(i)); + std::string bg_color = getBgColor(static_cast(i)); + toRGBA(fg_color, fg_rgba); + toRGBA(bg_color, bg_rgba); + + GtkColorButton *fg_btn = gtk_color_button_new(); + gtk_color_chooser_set_rgba(fg_btn, &fg_rgba); + ColorSet *fg = new ColorSet(static_cast(i), false, this); + g_signal_connect(fg_btn, "color_set", on_color_set, fg); + gtk_grid_attach(grid, fg_btn, 1, i + offset, 1, 1); + + GtkColorButton *bg_btn = gtk_color_button_new(); + gtk_color_chooser_set_rgba(bg_btn, &bg_rgba); + ColorSet *bg = new ColorSet(static_cast(i), true, this); + g_signal_connect(bg_btn, "color_set", on_color_set, bg); + gtk_grid_attach(grid, bg_btn, 2, i + offset, 1, 1); + + } + + gtk_container_add(content, grid); g_signal_connect(ok_btn, "clicked", on_setup_ok, this); g_signal_connect(dlg, "close", on_setup_close, this); @@ -527,8 +734,10 @@ void YellowNotes::reloadNotes(void *sender) delete note; it++; } + _notes.clear(); loadNotes(); + showNotes(sender); } @@ -582,6 +791,21 @@ std::string YellowNotes::currentLang() return _cfg[key]; } +bool YellowNotes::cfgOnDesktop() +{ + std::string key("on_desktop"); + return (_cfg[key] == "true") ? true : false; +} + +void YellowNotes::setCfgOnDesktop(bool y) +{ + std::string key("on_desktop"); + _cfg.erase(key); + std::string v = (y) ? "true" : "false"; + _cfg.insert(std::pair(key, v)); + saveConfig(); +} + void YellowNotes::setCurrentLang(const std::string &l) { std::string key("lang"); @@ -654,11 +878,22 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) _color = ColorType_t::YELLOW; _color_changed = false; + _in_transaction = true; + _hidden_loaded = false; + _pos_loaded = false; + _size_loaded = false; + _double_clicked = false; + _note_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_can_focus(_note_widget, true); gtk_window_set_decorated(_note_widget, false); +#ifdef _WIN32 gtk_window_set_type_hint(_note_widget, GDK_WINDOW_TYPE_HINT_POPUP_MENU); gtk_window_set_transient_for(_note_widget, _notes->topLevel()); +#endif +#ifdef __linux + gtk_window_set_type_hint(_note_widget, GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_UTILITY); +#endif _scroll_widget = gtk_scrolled_window_new(nullptr, nullptr); gtk_widget_set_vexpand(_scroll_widget, true); @@ -712,14 +947,22 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) width, height, nullptr ); _hide_image = gtk_image_new_from_pixbuf(hide_pixbuf); - gtk_widget_set_halign(_plus_image, GtkAlign::GTK_ALIGN_END); + gtk_widget_set_halign(_hide_image, GtkAlign::GTK_ALIGN_END); g_object_unref(hide_pixbuf); + GdkPixbuf *to_desktop_pixbuf = gdk_pixbuf_new_from_file_at_size(notes->imageFile("to_desktop").c_str(), + width, height, nullptr + ); + _to_desktop_image = gtk_image_new_from_pixbuf(to_desktop_pixbuf); + gtk_widget_set_halign(_to_desktop_image, GtkAlign::GTK_ALIGN_END); + g_object_unref(to_desktop_pixbuf); + gtk_container_add(_note_header, _color_image); gtk_container_add(_note_header, _title_label); gtk_container_add(_note_header, _plus_image); gtk_container_add(_note_header, _delete_image); gtk_container_add(_note_header, _hide_image); + gtk_container_add(_note_header, _to_desktop_image); gtk_container_add(_scroll_widget, _text_widget); @@ -733,6 +976,14 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) gtk_widget_show_all(_note_widget); + /*while (!gtk_widget_is_visible(_note_widget)) { + GdkEvent *e = gtk_get_current_event(); + if (e != nullptr) { + gtk_main_do_event(e); + gdk_event_free(e); + } + }*/ + //GdkWindow *window = gdk_window_get_effective_toplevel(gtk_widget_get_window(_note_widget)); //gdk_window_set_events(window, static_cast(gdk_window_get_events(window) | GDK_VISIBILITY_NOTIFY_MASK)); //gdk_window_set_override_redirect(window, true); @@ -753,6 +1004,7 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) g_object_ref(_delete_image); g_object_ref(_plus_image); g_object_ref(_hide_image); + g_object_ref(_to_desktop_image); load(); @@ -766,6 +1018,7 @@ YellowNote::~YellowNote() g_object_unref(_delete_image); g_object_unref(_plus_image); g_object_unref(_hide_image); + g_object_unref(_to_desktop_image); gtk_widget_destroy(_note_widget); _note_widget = nullptr; } @@ -854,6 +1107,7 @@ void YellowNote::updatePosition() void YellowNote::updateSize() { + std::cout << "Update size to: " << _width << ", " << _height << std::endl; gtk_window_resize(_note_widget, _width, _height); } @@ -876,63 +1130,39 @@ void YellowNote::hide() save(); } -void YellowNote::changed(GtkWidget *sender) + +void YellowNote::resized(int width, int height) { - bool sv = false; - - if (_color_changed) { - _color_changed = true; - sv = true; - } - - bool hidden = !gtk_widget_is_visible(_note_widget); - if (hidden != _hidden) { - _hidden = hidden; - sv = true; - } - - int w, h; - gtk_window_get_size(_note_widget, &w, &h); - if (w < 50) { w = 50; } - if (_width != w) { - _width = w; - sv = true; - } - - if (h < 50) { h = 50; } - if (_height != h) { - _height = h; - sv = true; - } - - int x, y; - gtk_window_get_position(_note_widget, &x, &y); - if (x <= 0) { x = 1; } - if (y <= 0) { y = 1; } - if (_x != x) { - _x = x; - sv = true; - } - if (_y != y) { - _y = y; - sv = true; - } - - const char *c_t = gtk_label_get_text (_title_label); - if (c_t != nullptr) { - std::string t(c_t); - if (t != _title) { - _title = t; - sv = true; - } - } - - if (sv) { save(); } + _width = width; + _height = height; + save(); } -void YellowNote::size_allocated(GtkWidget *sender, GtkAllocation *a) +void YellowNote::size_allocated(GtkWidget *sender, GtkAllocation *alloc) { - changed(sender); + std::cout << "loaded: " << _size_loaded << ", " << _pos_loaded << std::endl; + int width = alloc->width; + int height = alloc->height; + //if (_size_loaded) { + std::cout << "width, height = " << width << ", " << height << std::endl; + // _width = width; + // _height = height; + // save(); + // } + if (!_moving) { + if (width != _width || height != _height) { + gtk_window_resize(_note_widget, _width, _height); + } + } +} + +void YellowNote::positioned(GtkWidget *sender, int x, int y) +{ + if (_pos_loaded) { + _x = x; + _y = y; + save(); + } } void YellowNote::toFront() @@ -941,11 +1171,31 @@ void YellowNote::toFront() gtk_window_move(_note_widget, _x, _y); gtk_widget_hide(_note_widget); } else { + std::cout << "to_front x = " << _x << std::endl; + int x = _x; + int y = _y; gtk_window_present(_note_widget); - gtk_window_move(_note_widget, _x, _y); + gtk_window_move(_note_widget, x, y); } } + +void YellowNote::toDesktop() +{ +#ifdef __linux + std::cout << "todesktop: width: " << _width << ", height: " << _height << std::endl; + gtk_window_set_type_hint(_note_widget, GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_DESKTOP); +#endif +} + +void YellowNote::fromDesktop() +{ +#ifdef __linux + gtk_window_set_type_hint(_note_widget, GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_UTILITY); +#endif + toFront(); +} + void YellowNote::get_header_screen_coords(int &header_top, int &header_bottom) { int left, top; @@ -1000,6 +1250,9 @@ void YellowNote::adjustTitle(bool mutate) gtk_container_add(_note_header, _delete_image); gtk_container_remove(_note_header, _hide_image); gtk_container_add(_note_header, _hide_image); + gtk_container_remove(_note_header, _to_desktop_image); + gtk_container_add(_note_header, _to_desktop_image); + } bool YellowNote::windowPresented(void *sender, GdkEventVisibility *evt) // TODO according to docs this must not be a pointer @@ -1021,10 +1274,8 @@ void YellowNote::textChanged(void *sender) { if (_in_transaction) return; - std::cout << "Changed " << _save_id << std::endl; _save_counter++; if (_save_id == -1) { - std::cout << "Starting save timer" << std::endl; _save_id = _save_counter; g_timeout_add(1000, on_text_save_timeout, this); } @@ -1033,13 +1284,11 @@ void YellowNote::textChanged(void *sender) bool YellowNote::textSaveTimeout() { if (_save_counter != _save_id) { - std::cout << "Something changed" << std::endl; _save_id = _save_counter; g_timeout_add(1000, on_text_save_timeout, this); return false; } else { _save_id = -1; - std::cout << "Saving" << std::endl; save(); return false; } @@ -1070,6 +1319,21 @@ bool YellowNote::titleFocusOut(GtkWidget *sender, GdkEventFocus *evt) #define AROUND(c, n) ((c >= (n - threshold)) && (c <= (n + threshold))) +gboolean is_dblclk(gpointer d) +{ + YellowNote *n = static_cast(d); + n->doubleClicked(); + return false; + +} + +void YellowNote::doubleClicked() +{ + if (!_double_clicked) { + _notes->notesFromDesktop(nullptr); + } +} + bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) { int x = evt->x_root; @@ -1093,6 +1357,9 @@ bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) int hide_left, hide_right; get_screen_left_right(_hide_image, hide_left, hide_right); + int to_desktop_left, to_desktop_right; + get_screen_left_right(_to_desktop_image, to_desktop_left, to_desktop_right); + if (y >= header_top && y <= header_bottom) { if (x >= color_left && x <= color_right) { nextColor(); @@ -1106,6 +1373,10 @@ bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) hide(); return true; } + if (x >= to_desktop_left && x <= to_desktop_right) { + _notes->notesToDesktop(this); + return true; + } if (x >= delete_left && x <= delete_right) { deleteMe(); return true; @@ -1121,17 +1392,22 @@ bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) gtk_container_add(_note_header, _delete_image); gtk_container_remove(_note_header, _hide_image); gtk_container_add(_note_header, _hide_image); + gtk_container_remove(_note_header, _to_desktop_image); + gtk_container_add(_note_header, _to_desktop_image); gtk_widget_show(_title_entry); gtk_entry_set_text(_title_entry, _title.c_str()); gtk_widget_grab_focus(_title_entry); _editing_title = true; + _double_clicked = true; return true; } + _double_clicked = false; if (y >= header_top && y <= header_bottom) { _moving = true; _x_orig = evt->x; _y_orig = evt->y; + g_timeout_add(250, is_dblclk, this); return true; } @@ -1172,11 +1448,13 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) if (_moving) { int the_x = x - _x_orig; int the_y = y - _y_orig; + std::cout << "moving" << std::endl; gtk_window_move(_note_widget, the_x, the_y); + positioned(_note_widget, the_x, the_y); return true; } - if (_resize_bottom || _resize_right || _resize_edge) { + if (_resize_bottom || _resize_right || _resize_edge) { if (_resize_edge) { int left, top; gtk_window_get_position(_note_widget, &left, &top); @@ -1185,6 +1463,9 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) if (width < 100) { width = 100; } if (height < 60) { height = 60; } gtk_window_resize(_note_widget, width, height); + resized(width, height); + + //size_allocated(_note_box, width, height); return true; } @@ -1196,6 +1477,8 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) int width = x - left; if (width < 100) { width = 100; } gtk_window_resize(_note_widget, width, h); + resized(width, h); + //size_allocated(_note_box, width, h); return true; } @@ -1207,12 +1490,14 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) int height = y - top; if (height < 60) { height = 60; } gtk_window_resize(_note_widget, w, height); + resized(w, height); + //size_allocated(_note_box, w, height); return true; } } - int frame_bottom, frame_right; - get_frame_screen_coords(frame_bottom, frame_right); + int frame_bottom, frame_right; + get_frame_screen_coords(frame_bottom, frame_right); int header_top, header_bottom; get_header_screen_coords(header_top, header_bottom); @@ -1258,47 +1543,64 @@ void YellowNote::load() std::filesystem::path p(_filename); + int hidden, x, y, width, height; + ColorType_t c; + std::string title; + size_t s = 0; if (std::filesystem::is_regular_file(p)) { s = std::filesystem::file_size(p); + + FILE *f = fopen(_filename.c_str(), "rt"); + + if (f) { + int version = readInt(f, -1); + + hidden = readInt(f, -1); + x = readInt(f, 200); + y = readInt(f, 200); + width = readInt(f, 300); + height = readInt(f, 200); + + int color; + color = readInt(f, ColorType_t::YELLOW); + c = static_cast(color); + + char *buf = static_cast(malloc(s)); + memset(buf, 0, s); + + fgets(buf, s, f); + title = buf; + trim(title); + + memset(buf, 0, s); + int pos = ftell(f); + int bytes = s - pos; + fread(buf, bytes, 1, f); + + fclose(f); + gtk_text_buffer_set_text(_buffer, buf, strlen(buf)); + free(buf); + + _title = title; + updateTitle(); + + _color = c; + updateColor(); + + _x = x; _y = y; + _pos_loaded = true; + updatePosition(); + + _width = width; _height = height; + _size_loaded = true; + updateSize(); + + _hidden = hidden; + _hidden_loaded = true; + updateHidden(); + } } - FILE *f = fopen(_filename.c_str(), "rt"); - - if (f) { - int version = readInt(f, -1); - - _hidden = readInt(f, -1); - _x = readInt(f, 200); - _y = readInt(f, 200); - _width = readInt(f, 300); - _height = readInt(f, 200); - - int color; - color = readInt(f, ColorType_t::YELLOW); - _color = static_cast(color); - - char *buf = static_cast(malloc(s)); - memset(buf, 0, s); - - fgets(buf, s, f); - _title = buf; - trim(_title); - - memset(buf, 0, s); - int pos = ftell(f); - int bytes = s - pos; - fread(buf, bytes, 1, f); - - fclose(f); - gtk_text_buffer_set_text(_buffer, buf, strlen(buf)); - free(buf); - } - - updateTitle(); - updateColor(); - updatePosition(); - updateSize(); - updateHidden(); _in_transaction = false; } @@ -1309,6 +1611,8 @@ void YellowNote::save() return; } + std::cout << "Saving " << _title << "..." << _size_loaded << ", " << _width << ", h = " << _height << std::endl; + std::filesystem::path p(_filename); FILE *f = fopen(_filename.c_str(), "wt"); if (f) { diff --git a/yellownotes.h b/yellownotes.h index 11d02d5..be20dce 100644 --- a/yellownotes.h +++ b/yellownotes.h @@ -10,6 +10,7 @@ extern "C" { } class YellowNote; +class ColorSet; typedef enum { DARK = 0, @@ -32,6 +33,8 @@ private: void *_dlg; void *_langs; + std::list _color_sets; + std::list _notes; int _font_size; GtkWindow *_toplevel; @@ -58,6 +61,8 @@ public: void popupTrayMenu(void *sender); void newNote(void *sender); void showNotes(void *sender); + void notesToDesktop(void *sender); + void notesFromDesktop(void *sender); void reloadNotes(void *sender); void quit(void *sender); void topLevelHidden(GtkWidget *sender); @@ -70,10 +75,19 @@ public: public: std::string currentLang(); void setCurrentLang(const std::string &l); + bool cfgOnDesktop(); + void setCfgOnDesktop(bool y); + std::string getFgColor(ColorType_t type); + std::string getBgColor(ColorType_t type); + void setFgColor(ColorType_t type, const std::string &col); + void setBgColor(ColorType_t type, const std::string &col); + std::string fromRGBA(const GdkRGBA &rgba); + void toRGBA(const std::string &col, GdkRGBA &rgba); public: YellowNotes(void *app); ~YellowNotes(); + void colorSet(void *sender); }; #define YELLOWNOTES(obj) reinterpret_cast(obj) From 6cfa0d5a2df8eaaaf16d0b8dd093f5cfc0d990fb Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Mon, 24 Nov 2025 14:52:58 +0100 Subject: [PATCH 2/6] application path --- exe_path.cpp | 20 ++ exe_path.h | 14 + utils/whereami.c | 815 +++++++++++++++++++++++++++++++++++++++++++++++ utils/whereami.h | 69 ++++ 4 files changed, 918 insertions(+) create mode 100644 exe_path.cpp create mode 100644 exe_path.h create mode 100644 utils/whereami.c create mode 100644 utils/whereami.h diff --git a/exe_path.cpp b/exe_path.cpp new file mode 100644 index 0000000..ecbd4c6 --- /dev/null +++ b/exe_path.cpp @@ -0,0 +1,20 @@ +#include "exe_path.h" + +#include "utils/whereami.h" + +#include + +std::string WhereAmI::containing_folder() +{ + int len = wai_getExecutablePath(NULL, 0, NULL); + + char *path = static_cast(malloc(len + 1)); + wai_getExecutablePath(path, len, NULL); + path[len] = '\0'; + + std::string p(path); + std::cout << p << std::endl; + return p; +} + +WhereAmI::WhereAmI() {} diff --git a/exe_path.h b/exe_path.h new file mode 100644 index 0000000..e532334 --- /dev/null +++ b/exe_path.h @@ -0,0 +1,14 @@ +#ifndef EXE_PATH_H +#define EXE_PATH_H + +#include + +class WhereAmI +{ +public: + std::string containing_folder(); +public: + WhereAmI(); +}; + +#endif // EXE_PATH_H diff --git a/utils/whereami.c b/utils/whereami.c new file mode 100644 index 0000000..37397d4 --- /dev/null +++ b/utils/whereami.c @@ -0,0 +1,815 @@ +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +// in case you want to #include "whereami.c" in a larger compilation unit +#if !defined(WHEREAMI_H) +#include "whereami.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__linux__) || defined(__CYGWIN__) +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#elif defined(__APPLE__) +#undef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE +#define _DARWIN_BETTER_REALPATH +#endif + +#if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) +#include +#endif + +#if !defined(WAI_MALLOC) +#define WAI_MALLOC(size) malloc(size) +#endif + +#if !defined(WAI_FREE) +#define WAI_FREE(p) free(p) +#endif + +#if !defined(WAI_REALLOC) +#define WAI_REALLOC(p, size) realloc(p, size) +#endif + +#ifndef WAI_NOINLINE +#if defined(_MSC_VER) +#define WAI_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +#define WAI_NOINLINE __attribute__((noinline)) +#else +#error unsupported compiler +#endif +#endif + +#if defined(_MSC_VER) +#define WAI_RETURN_ADDRESS() _ReturnAddress() +#elif defined(__GNUC__) +#define WAI_RETURN_ADDRESS() __builtin_extract_return_addr(__builtin_return_address(0)) +#else +#error unsupported compiler +#endif + +#if defined(_WIN32) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#if defined(_MSC_VER) +#pragma warning(push, 3) +#endif +#include +#include +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +#if (_MSC_VER >= 1900) +#include +#else +#define bool int +#define false 0 +#define true 1 +#endif + +static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) +{ + wchar_t buffer1[MAX_PATH]; + wchar_t buffer2[MAX_PATH]; + wchar_t* path = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + DWORD size; + int length_, length__; + + size = GetModuleFileNameW(module, buffer1, sizeof(buffer1) / sizeof(buffer1[0])); + + if (size == 0) + break; + else if (size == (DWORD)(sizeof(buffer1) / sizeof(buffer1[0]))) + { + DWORD size_ = size; + do + { + wchar_t* path_; + + path_ = (wchar_t*)WAI_REALLOC(path, sizeof(wchar_t) * size_ * 2); + if (!path_) + break; + size_ *= 2; + path = path_; + size = GetModuleFileNameW(module, path, size_); + } + while (size == size_); + + if (size == size_) + break; + } + else + path = buffer1; + + if (!_wfullpath(buffer2, path, MAX_PATH)) + break; + length_ = (int)wcslen(buffer2); + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_ , out, capacity, NULL, NULL); + + if (length__ == 0) + length__ = WideCharToMultiByte(CP_UTF8, 0, buffer2, length_, NULL, 0, NULL, NULL); + if (length__ == 0) + break; + + if (length__ <= capacity && dirname_length) + { + int i; + + for (i = length__ - 1; i >= 0; --i) + { + if (out[i] == '\\') + { + *dirname_length = i; + break; + } + } + } + + length = length__; + } + + if (path != buffer1) + WAI_FREE(path); + + return ok ? length : -1; +} + +WAI_NOINLINE WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length); +} + +WAI_NOINLINE WAI_FUNCSPEC + int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + HMODULE module; + int length = -1; + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4054) +#endif + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)WAI_RETURN_ADDRESS(), &module)) +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + { + length = WAI_PREFIX(getModulePath_)(module, out, capacity, dirname_length); + } + + return length; +} + +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__sun) || defined(WAI_USE_PROC_SELF_EXE) + +#include +#include +#include +#if defined(__linux__) +#include +#else +#include +#endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#if defined(__sun) +#define WAI_PROC_SELF_EXE "/proc/self/path/a.out" +#else +#define WAI_PROC_SELF_EXE "/proc/self/exe" +#endif +#endif + +WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + resolved = realpath(WAI_PROC_SELF_EXE, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + return ok ? length : -1; +} + +#if !defined(WAI_PROC_SELF_MAPS_RETRY) +#define WAI_PROC_SELF_MAPS_RETRY 5 +#endif + +#if !defined(WAI_PROC_SELF_MAPS) +#if defined(__sun) +#define WAI_PROC_SELF_MAPS "/proc/self/map" +#else +#define WAI_PROC_SELF_MAPS "/proc/self/maps" +#endif +#endif + +#if !defined(WAI_STRINGIZE) +#define WAI_STRINGIZE(s) +#define WAI_STRINGIZE_(s) #s +#endif + +#if defined(__ANDROID__) || defined(ANDROID) +#include +#include +#include +#endif +#include + +WAI_NOINLINE WAI_FUNCSPEC + int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + int length = -1; + FILE* maps = NULL; + + for (int r = 0; r < WAI_PROC_SELF_MAPS_RETRY; ++r) + { + maps = fopen(WAI_PROC_SELF_MAPS, "r"); + if (!maps) + break; + + for (;;) + { + char buffer[128 + PATH_MAX]; + uintptr_t low, high; + char perms[5]; + uint64_t offset; + uint32_t major, minor, inode; + char path[PATH_MAX + 1]; + + if (!fgets(buffer, sizeof(buffer), maps)) + break; + + if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) + { + void* _addr = WAI_RETURN_ADDRESS(); + uintptr_t addr = (uintptr_t)_addr; + if (low <= addr && addr <= high) + { + char* resolved; + + resolved = realpath(path, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); +#if defined(__ANDROID__) || defined(ANDROID) + if (length > 4 + &&buffer[length - 1] == 'k' + &&buffer[length - 2] == 'p' + &&buffer[length - 3] == 'a' + &&buffer[length - 4] == '.') + { + int fd = open(path, O_RDONLY); + if (fd == -1) + { + length = -1; // retry + break; + } + + char* begin = (char*)mmap(0, offset, PROT_READ, MAP_SHARED, fd, 0); + if (begin == MAP_FAILED) + { + close(fd); + length = -1; // retry + break; + } + + char* p = begin + offset - 30; // minimum size of local file header + while (p >= begin) // scan backwards + { + if (*((uint32_t*)p) == 0x04034b50UL) // local file header signature found + { + uint16_t length_ = *((uint16_t*)(p + 26)); + + if (length + 2 + length_ < (int)sizeof(buffer)) + { + memcpy(&buffer[length], "!/", 2); + memcpy(&buffer[length + 2], p + 30, length_); + length += 2 + length_; + } + + break; + } + + --p; + } + + munmap(begin, offset); + close(fd); + } +#endif + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + + break; + } + } + } + + fclose(maps); + maps = NULL; + + if (length != -1) + break; + } + + return length; +} + +#elif defined(__APPLE__) + +#include +#include +#include +#include +#include +#include + +WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + uint32_t size = (uint32_t)sizeof(buffer1); + if (_NSGetExecutablePath(path, &size) == -1) + { + path = (char*)WAI_MALLOC(size); + if (!_NSGetExecutablePath(path, &size)) + break; + } + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (path != buffer1) + WAI_FREE(path); + + return ok ? length : -1; +} + +WAI_NOINLINE WAI_FUNCSPEC + int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__QNXNTO__) + +#include +#include +#include +#include +#include +#include + +#if !defined(WAI_PROC_SELF_EXE) +#define WAI_PROC_SELF_EXE "/proc/self/exefile" +#endif + +WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* resolved = NULL; + FILE* self_exe = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + self_exe = fopen(WAI_PROC_SELF_EXE, "r"); + if (!self_exe) + break; + + if (!fgets(buffer1, sizeof(buffer1), self_exe)) + break; + + resolved = realpath(buffer1, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + fclose(self_exe); + + return ok ? length : -1; +} + +WAI_FUNCSPEC + int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#elif defined(__DragonFly__) || defined(__FreeBSD__) || \ +defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__OpenBSD__) + +#include + + WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[4096]; + char buffer2[PATH_MAX]; + char buffer3[PATH_MAX]; + char** argv = (char**)buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t size; + + if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0) + break; + + if (size > sizeof(buffer1)) + { + argv = (char**)WAI_MALLOC(size); + if (!argv) + break; + } + + if (sysctl(mib, 4, argv, &size, NULL, 0) != 0) + break; + + if (strchr(argv[0], '/')) + { + resolved = realpath(argv[0], buffer2); + if (!resolved) + break; + } + else + { + const char* PATH = getenv("PATH"); + if (!PATH) + break; + + size_t argv0_length = strlen(argv[0]); + + const char* begin = PATH; + while (1) + { + const char* separator = strchr(begin, ':'); + const char* end = separator ? separator : begin + strlen(begin); + + if (end - begin > 0) + { + if (*(end -1) == '/') + --end; + + if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2)) + { + memcpy(buffer2, begin, end - begin); + buffer2[end - begin] = '/'; + memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1); + + resolved = realpath(buffer2, buffer3); + if (resolved) + break; + } + } + + if (!separator) + break; + + begin = ++separator; + } + + if (!resolved) + break; + } + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (argv != (char**)buffer1) + WAI_FREE(argv); + + return ok ? length : -1; +} + +#else + +WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[PATH_MAX]; + char buffer2[PATH_MAX]; + char* path = buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { +#if defined(__NetBSD__) + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; +#else + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; +#endif + size_t size = sizeof(buffer1); + + if (sysctl(mib, 4, path, &size, NULL, 0) != 0) + break; + + resolved = realpath(path, buffer2); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + return ok ? length : -1; +} + +#endif + +WAI_NOINLINE WAI_FUNCSPEC + int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) +{ + char buffer[PATH_MAX]; + char* resolved = NULL; + int length = -1; + + for(;;) + { + Dl_info info; + + if (dladdr(WAI_RETURN_ADDRESS(), &info)) + { + resolved = realpath(info.dli_fname, buffer); + if (!resolved) + break; + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + break; + } + + return length; +} + +#else + +#error unsupported platform + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/utils/whereami.h b/utils/whereami.h new file mode 100644 index 0000000..2380aaf --- /dev/null +++ b/utils/whereami.h @@ -0,0 +1,69 @@ +// (‑●‑●)> dual licensed under the WTFPL v2 and MIT licenses +// without any warranty. +// by Gregory Pakosz (@gpakosz) +// https://github.com/gpakosz/whereami + +#ifndef WHEREAMI_H +#define WHEREAMI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef WAI_FUNCSPEC +#define WAI_FUNCSPEC +#endif +#ifndef WAI_PREFIX +#define WAI_PREFIX(function) wai_##function +#endif + +/** + * Returns the path to the current executable. + * + * Usage: + * - first call `int length = wai_getExecutablePath(NULL, 0, NULL);` to + * retrieve the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getExecutablePath(path, length, NULL)` again to retrieve the + * path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. Available only when `capacity` is large enough to retrieve the + * path. + * + * @return the length of the executable path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC + int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); + +/** + * Returns the path to the current module + * + * Usage: + * - first call `int length = wai_getModulePath(NULL, 0, NULL);` to retrieve + * the length of the path + * - allocate the destination buffer with `path = (char*)malloc(length + 1);` + * - call `wai_getModulePath(path, length, NULL)` again to retrieve the path + * - add a terminal NUL character with `path[length] = '\0';` + * + * @param out destination buffer, optional + * @param capacity destination buffer capacity + * @param dirname_length optional recipient for the length of the dirname part + * of the path. Available only when `capacity` is large enough to retrieve the + * path. + * + * @return the length of the module path on success (without a terminal NUL + * character), otherwise `-1` + */ +WAI_FUNCSPEC + int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length); + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef WHEREAMI_H From 9befee44a57a2a1c078daa21e88984c15591e413 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Mon, 24 Nov 2025 15:00:39 +0100 Subject: [PATCH 3/6] color updates --- yellownotes.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/yellownotes.cpp b/yellownotes.cpp index f83721c..786bc14 100644 --- a/yellownotes.cpp +++ b/yellownotes.cpp @@ -102,7 +102,6 @@ private: void updatePosition(); void updateHidden(); void updateSize(); - void updateColor(); void adjustTitle(bool mutate); @@ -125,6 +124,7 @@ public: void toFront(); void toDesktop(); void fromDesktop(); + void updateColor(); public: bool move_begin(GtkWidget *sender, GdkEventButton *evt); @@ -648,7 +648,15 @@ void YellowNotes::setupClose(GtkWidget *sender) _dlg = nullptr; _langs = nullptr; + saveConfig(); + + std::list::iterator n_it; + for(n_it = _notes.begin(); n_it != _notes.end(); n_it++) { + YellowNote *n = *n_it; + n->updateColor(); + } + } else { } } From aaeb7937039127ca943aed598c2c3df81fc5594d Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Mon, 24 Nov 2025 16:24:35 +0100 Subject: [PATCH 4/6] Settings - font sizes --- gtk-imports.h | 5 ++ title_only.png | Bin 0 -> 7301 bytes title_only.svg | 2 + tr.cpp | 39 ++++++++-- yellownotes.cpp | 192 +++++++++++++++++++++++++++++++++++++++--------- yellownotes.h | 8 +- 6 files changed, 201 insertions(+), 45 deletions(-) create mode 100644 title_only.png create mode 100644 title_only.svg diff --git a/gtk-imports.h b/gtk-imports.h index 42b686e..20c3eaf 100644 --- a/gtk-imports.h +++ b/gtk-imports.h @@ -73,6 +73,7 @@ typedef void GtkComboBox; typedef void GtkGrid; typedef void GtkColorButton; typedef void GtkColorChooser; +typedef void GtkSpinButton; typedef int gboolean; typedef int gint; @@ -669,6 +670,10 @@ DECL(GdkEvent*, gtk_get_current_event, (void )) DECL(void, gtk_main_do_event, (GdkEvent* event)) DECL(void, gdk_event_free, (GdkEvent* event)) +DECL(GtkWidget*, gtk_spin_button_new_with_range, (gdouble min, gdouble max, gdouble step)) +DECL(void, gtk_spin_button_set_value, (GtkSpinButton* spin_button, gdouble value )) +DECL(gint, gtk_spin_button_get_value_as_int, (GtkSpinButton* spin_button )) + DECL(unsigned long, g_signal_connect_data, (GObject *obj, const char *signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags)) // Messages diff --git a/title_only.png b/title_only.png new file mode 100644 index 0000000000000000000000000000000000000000..c60b6272cb196bf9fa6f198d92f375f52b913828 GIT binary patch literal 7301 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 + \ No newline at end of file diff --git a/tr.cpp b/tr.cpp index e217f8b..9db430b 100644 --- a/tr.cpp +++ b/tr.cpp @@ -1,5 +1,6 @@ #include "tr.h" #include +#include void tr::add(const char *sentence, ...) { @@ -39,9 +40,12 @@ const char *tr::translate(const char *str) { std::unordered_map::iterator it; + if (_lang == "en") { return str; } + it = _translations.find(_lang); if (it == _translations.end()) { + std::cerr << "No translation for: " << str << std::endl; return str; } else { Translations_t *m = it->second; @@ -49,6 +53,7 @@ const char *tr::translate(const char *str) std::string s(str); n_it = m->find(s); if (n_it == m->end()) { + std::cerr << "No translation for: " << str << std::endl; return str; } else { return n_it->second.c_str(); @@ -61,14 +66,36 @@ void tr::setLang(const std::string &l) _lang = l; } +#define nl(a, b) add(a, "nl:" b, nullptr) +#define en(a, b) add(a, "en:" b, nullptr) + tr::tr() { - add("Quit", "nl:Beëindigen", nullptr); - add("New Note", "nl:Nieuwe Notitie", nullptr); - add("Show Notes", "nl:Notities Presenteren", nullptr); - add("Hide Notes", "nl:Notities Verbergen", nullptr); - add("Reload Notes", "nl:Notities opnieuw laden", nullptr); - add("Setup", "nl:Instellingen", nullptr); + + nl("Quit", "Beëindigen"); + nl("New Note", "Nieuwe Notitie"); + nl("Show Notes", "Notities Presenteren"); + nl("Hide Notes", "Notities Verbergen"); + nl("Reload Notes", "Notities opnieuw laden"); + nl("Setup", "Instellingen"); + nl("Notes on desktop", "Noties naar achteren"); + nl("Language:", "Taalinstelling:"); + nl("Language:", "Taalinstelling:"); + nl("Ok", "Ok"); + nl("Yellownotes Setup", "Yellownotes Instellingen"); + nl("Foreground Color", "Voorgrond kleur"); + nl("Background Color", "Achtergrond kleur"); + nl("Dark", "Donker"); + nl("Yellow", "Geel"); + nl("Orange", "Oranje"); + nl("Blue", "Blauw"); + nl("Cyan", "Cyaan"); + nl("Green", "Groen"); + nl("Red", "Rood"); + nl("Grey", "Grijs"); + nl("Font size:", "Lettertype Grootte:"); + nl("Actual Font Size in Note", "Werkelijke lettertype grootte in de notitie"); + _lang = "en"; } diff --git a/yellownotes.cpp b/yellownotes.cpp index 786bc14..fa962e1 100644 --- a/yellownotes.cpp +++ b/yellownotes.cpp @@ -52,6 +52,7 @@ private: GtkImage *_plus_image; GtkImage *_hide_image; GtkImage *_to_desktop_image; + GtkImage *_title_only_image; GtkWidget *_title_label; GtkWidget *_title_entry; GtkWidget *_title_separator; @@ -67,6 +68,9 @@ private: bool _hidden; bool _hidden_loaded; + bool _title_only; + bool _title_only_loaded; + int _x; int _y; bool _pos_loaded; @@ -102,6 +106,7 @@ private: void updatePosition(); void updateHidden(); void updateSize(); + void updateTitleOnly(); void adjustTitle(bool mutate); @@ -125,6 +130,7 @@ public: void toDesktop(); void fromDesktop(); void updateColor(); + void toggleTitleOnly(); public: bool move_begin(GtkWidget *sender, GdkEventButton *evt); @@ -142,6 +148,7 @@ public: std::string title(); bool isHidden(); void doubleClicked(); + YellowNotes *notes(); public: void load(); @@ -152,11 +159,14 @@ public: ~YellowNote(); }; -class ColorSet +class SettingContainer { public: ColorType_t color; + GtkLabel *font_label; + GtkSpinButton *font_size_btn; YellowNotes *notes; + YellowNote *note; bool bg; public: @@ -171,14 +181,31 @@ public: } } - ColorSet(ColorType_t t, bool _bg, YellowNotes *n) { + void fontSizeSet(GtkWidget *Sender) { + int size = gtk_spin_button_get_value_as_int(font_size_btn); + notes->updateWidgetCss(font_label, ColorType_t::YELLOW); + notes->setFontSize(size); + } + + SettingContainer(ColorType_t t, bool _bg, YellowNotes *n) { color = t; bg = _bg; notes = n; + font_label = nullptr; + font_size_btn = nullptr; + } + + SettingContainer(GtkSpinButton *btn, GtkLabel *fl, YellowNotes *n) { + color = FIRST; + font_label = fl; + font_size_btn = btn; + notes = n; + bg = false; } }; -SIGNAL(ColorSet, on_color_set, colorSet); +SIGNAL(SettingContainer, on_color_set, colorSet); +SIGNAL(SettingContainer, on_font_size_set, fontSizeSet); SIGNAL2(YellowNote, on_size_allocated, size_allocated, GtkAllocation) BSIGNAL2(YellowNote, on_button_press, move_begin, GdkEventButton); @@ -284,6 +311,20 @@ void YellowNotes::toRGBA(const std::string &col, GdkRGBA &rgba) rgba.red = red; } +void YellowNotes::updateWidgetCss(GtkWidget *w, ColorType_t col) +{ + auto set_style = [this, col](GtkWidget *widget) { + GtkStyleContext *c = gtk_widget_get_style_context(widget); + const char *style = gtk_style_context_to_string(c, GTK_STYLE_CONTEXT_PRINT_RECURSE); + GtkCssProvider *css_p = gtk_css_provider_new(); + gtk_style_context_add_provider(c, css_p, GTK_STYLE_PROVIDER_PRIORITY_USER); + std::string widget_css = css(col); + gtk_css_provider_load_from_data(css_p, widget_css.c_str(), widget_css.size(), nullptr); + }; + + set_style(w); +} + std::string YellowNotes::getFgColor(ColorType_t type) { char buf[100]; @@ -395,9 +436,28 @@ std::string YellowNotes::css(ColorType_t type) int YellowNotes::fontSize() { + std::string key("font_size"); + std::unordered_map::iterator it; + it = _cfg.find(key); + if (it != _cfg.end()) { + _font_size = atoi(it->second.c_str()); + if (_font_size < 6 || _font_size > 30) { _font_size = 15; } + } return _font_size; } +void YellowNotes::setFontSize(int size) +{ + _font_size = size; + char buf[100]; + sprintf(buf, "%d", size); + std::string v = buf; + std::string key("font_size"); + _cfg.erase(key); + _cfg.insert(std::pair(key, v)); + saveConfig(); +} + int YellowNotes::iconSize() { return _font_size * 1.5; @@ -520,7 +580,6 @@ void YellowNotes::loadConfig() } setLang(currentLang()); - } void YellowNotes::saveConfig() @@ -639,12 +698,12 @@ void YellowNotes::setupClose(GtkWidget *sender) setCurrentLang(lang); gtk_widget_destroy(_dlg); - std::list::iterator it; - for(it = _color_sets.begin() ; it != _color_sets.end(); it++) { - ColorSet *s = *it; + std::list::iterator it; + for(it = _settings_containers.begin() ; it != _settings_containers.end(); it++) { + SettingContainer *s = *it; delete s; } - _color_sets.clear(); + _settings_containers.clear(); _dlg = nullptr; _langs = nullptr; @@ -689,7 +748,7 @@ void YellowNotes::setup(void *sender) gtk_grid_attach(grid, lbl_langs, 0, 0, 1, 1); gtk_grid_attach(grid, langs, 1, 0, 2, 1); - GtkLabel *lbl_fg = gtk_label_new(_("Forground Color")); + GtkLabel *lbl_fg = gtk_label_new(_("Foreground Color")); GtkLabel *lbl_bg = gtk_label_new(_("Background Color")); gtk_grid_attach(grid, lbl_fg, 1, 1, 1, 1); gtk_grid_attach(grid, lbl_bg, 2, 1, 1, 1); @@ -713,18 +772,35 @@ void YellowNotes::setup(void *sender) GtkColorButton *fg_btn = gtk_color_button_new(); gtk_color_chooser_set_rgba(fg_btn, &fg_rgba); - ColorSet *fg = new ColorSet(static_cast(i), false, this); + SettingContainer *fg = new SettingContainer(static_cast(i), false, this); + _settings_containers.push_back(fg); g_signal_connect(fg_btn, "color_set", on_color_set, fg); gtk_grid_attach(grid, fg_btn, 1, i + offset, 1, 1); GtkColorButton *bg_btn = gtk_color_button_new(); gtk_color_chooser_set_rgba(bg_btn, &bg_rgba); - ColorSet *bg = new ColorSet(static_cast(i), true, this); + SettingContainer *bg = new SettingContainer(static_cast(i), true, this); + _settings_containers.push_back(bg); g_signal_connect(bg_btn, "color_set", on_color_set, bg); gtk_grid_attach(grid, bg_btn, 2, i + offset, 1, 1); - } + offset = i + offset; + + gtk_grid_attach(grid, gtk_label_new(_("Font size:")), 0, offset, 1, 1); + GtkSpinButton *fs = gtk_spin_button_new_with_range(6.0, 20.0, 1.0); + gtk_spin_button_set_value(fs, fontSize()); + gtk_grid_attach(grid, fs, 1, offset, 1, 1); + + GtkLabel *font_label = gtk_label_new(_("Actual Font Size in Note")); + gtk_widget_set_size_request(font_label, 400, -1); + gtk_grid_attach(grid, font_label, 2, offset, 1, 1); + + SettingContainer *fl = new SettingContainer(fs, font_label, this); + _settings_containers.push_back(fl); + g_signal_connect(fs, "value_changed", on_font_size_set, fl); + fl->fontSizeSet(fs); + gtk_container_add(content, grid); g_signal_connect(ok_btn, "clicked", on_setup_ok, this); @@ -874,6 +950,7 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) _width = 300; _height = 200; _hidden = false; + _title_only = false; _editing_title = false; _save_counter = 0; _save_id = -1; @@ -965,12 +1042,21 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) gtk_widget_set_halign(_to_desktop_image, GtkAlign::GTK_ALIGN_END); g_object_unref(to_desktop_pixbuf); + GdkPixbuf *title_only_pixbuf = gdk_pixbuf_new_from_file_at_size(notes->imageFile("title_only").c_str(), + width, height, nullptr + ); + _title_only_image = gtk_image_new_from_pixbuf(title_only_pixbuf); + gtk_widget_set_halign(_title_only_image, GtkAlign::GTK_ALIGN_END); + g_object_unref(title_only_pixbuf); + + gtk_container_add(_note_header, _color_image); gtk_container_add(_note_header, _title_label); gtk_container_add(_note_header, _plus_image); gtk_container_add(_note_header, _delete_image); gtk_container_add(_note_header, _hide_image); gtk_container_add(_note_header, _to_desktop_image); + gtk_container_add(_note_header, _title_only_image); gtk_container_add(_scroll_widget, _text_widget); @@ -1013,6 +1099,7 @@ YellowNote::YellowNote(YellowNotes *notes, const std::string &filename) g_object_ref(_plus_image); g_object_ref(_hide_image); g_object_ref(_to_desktop_image); + g_object_ref(_title_only_image); load(); @@ -1027,6 +1114,7 @@ YellowNote::~YellowNote() g_object_unref(_plus_image); g_object_unref(_hide_image); g_object_unref(_to_desktop_image); + g_object_unref(_title_only_image); gtk_widget_destroy(_note_widget); _note_widget = nullptr; } @@ -1043,6 +1131,7 @@ void YellowNote::updateWidgetColors(GtkWidget *w) }; set_style(w); + _notes->updateWidgetCss(w, _color); } void YellowNote::updateColor() @@ -1102,6 +1191,19 @@ void YellowNote::updateTitle() gtk_label_set_label(_title_label, _title.c_str()); } +void YellowNote::updateTitleOnly() +{ + if (_title_only) { + gtk_widget_hide(_scroll_widget); + GtkAllocation alloc; + gtk_widget_get_allocation(_note_header, &alloc); + gtk_window_resize(_note_widget, _width, alloc.height); + } else { + gtk_widget_show_all(_scroll_widget); + gtk_window_resize(_note_widget, _width, _height); + } +} + void YellowNote::updateHidden() { if (_hidden) { hide(); } @@ -1115,8 +1217,8 @@ void YellowNote::updatePosition() void YellowNote::updateSize() { - std::cout << "Update size to: " << _width << ", " << _height << std::endl; - gtk_window_resize(_note_widget, _width, _height); + updateTitleOnly(); + //gtk_window_resize(_note_widget, _width, _height); } void YellowNote::showNote(GtkWidget *sender) @@ -1138,6 +1240,12 @@ void YellowNote::hide() save(); } +void YellowNote::toggleTitleOnly() +{ + _title_only = !_title_only; + updateTitleOnly(); + save(); +} void YellowNote::resized(int width, int height) { @@ -1148,18 +1256,12 @@ void YellowNote::resized(int width, int height) void YellowNote::size_allocated(GtkWidget *sender, GtkAllocation *alloc) { - std::cout << "loaded: " << _size_loaded << ", " << _pos_loaded << std::endl; int width = alloc->width; int height = alloc->height; - //if (_size_loaded) { - std::cout << "width, height = " << width << ", " << height << std::endl; - // _width = width; - // _height = height; - // save(); - // } if (!_moving) { if (width != _width || height != _height) { - gtk_window_resize(_note_widget, _width, _height); + updateSize(); + //gtk_window_resize(_note_widget, _width, _height); } } } @@ -1179,7 +1281,6 @@ void YellowNote::toFront() gtk_window_move(_note_widget, _x, _y); gtk_widget_hide(_note_widget); } else { - std::cout << "to_front x = " << _x << std::endl; int x = _x; int y = _y; gtk_window_present(_note_widget); @@ -1191,7 +1292,6 @@ void YellowNote::toFront() void YellowNote::toDesktop() { #ifdef __linux - std::cout << "todesktop: width: " << _width << ", height: " << _height << std::endl; gtk_window_set_type_hint(_note_widget, GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_DESKTOP); #endif } @@ -1260,6 +1360,8 @@ void YellowNote::adjustTitle(bool mutate) gtk_container_add(_note_header, _hide_image); gtk_container_remove(_note_header, _to_desktop_image); gtk_container_add(_note_header, _to_desktop_image); + gtk_container_remove(_note_header, _title_only_image); + gtk_container_add(_note_header, _title_only_image); } @@ -1342,6 +1444,11 @@ void YellowNote::doubleClicked() } } +YellowNotes *YellowNote::notes() +{ + return _notes; +} + bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) { int x = evt->x_root; @@ -1368,6 +1475,9 @@ bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) int to_desktop_left, to_desktop_right; get_screen_left_right(_to_desktop_image, to_desktop_left, to_desktop_right); + int title_only_left, title_only_right; + get_screen_left_right(_title_only_image, title_only_left, title_only_right); + if (y >= header_top && y <= header_bottom) { if (x >= color_left && x <= color_right) { nextColor(); @@ -1385,6 +1495,10 @@ bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) _notes->notesToDesktop(this); return true; } + if (x >= title_only_left && x <= title_only_right) { + toggleTitleOnly(); + return true; + } if (x >= delete_left && x <= delete_right) { deleteMe(); return true; @@ -1402,6 +1516,8 @@ bool YellowNote::move_begin(GtkWidget *sender, GdkEventButton *evt) gtk_container_add(_note_header, _hide_image); gtk_container_remove(_note_header, _to_desktop_image); gtk_container_add(_note_header, _to_desktop_image); + gtk_container_remove(_note_header, _title_only_image); + gtk_container_add(_note_header, _title_only_image); gtk_widget_show(_title_entry); gtk_entry_set_text(_title_entry, _title.c_str()); gtk_widget_grab_focus(_title_entry); @@ -1456,7 +1572,6 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) if (_moving) { int the_x = x - _x_orig; int the_y = y - _y_orig; - std::cout << "moving" << std::endl; gtk_window_move(_note_widget, the_x, the_y); positioned(_note_widget, the_x, the_y); return true; @@ -1472,8 +1587,6 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) if (height < 60) { height = 60; } gtk_window_resize(_note_widget, width, height); resized(width, height); - - //size_allocated(_note_box, width, height); return true; } @@ -1486,7 +1599,6 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) if (width < 100) { width = 100; } gtk_window_resize(_note_widget, width, h); resized(width, h); - //size_allocated(_note_box, width, h); return true; } @@ -1499,7 +1611,6 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) if (height < 60) { height = 60; } gtk_window_resize(_note_widget, w, height); resized(w, height); - //size_allocated(_note_box, w, height); return true; } } @@ -1533,7 +1644,7 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt) return false; } -#define YELLOWNOTE_VERSION 1 +#define YELLOWNOTE_VERSION 2 void YellowNote::load() { @@ -1554,6 +1665,7 @@ void YellowNote::load() int hidden, x, y, width, height; ColorType_t c; std::string title; + bool title_only; size_t s = 0; if (std::filesystem::is_regular_file(p)) { @@ -1574,6 +1686,11 @@ void YellowNote::load() color = readInt(f, ColorType_t::YELLOW); c = static_cast(color); + if (version >= 2) { + int t = readInt(f, 0); + title_only = (t) ? true : false; + } + char *buf = static_cast(malloc(s)); memset(buf, 0, s); @@ -1600,13 +1717,17 @@ void YellowNote::load() _pos_loaded = true; updatePosition(); - _width = width; _height = height; - _size_loaded = true; - updateSize(); - _hidden = hidden; _hidden_loaded = true; updateHidden(); + + _title_only = title_only; + _title_only_loaded = true; + updateTitleOnly(); + + _width = width; _height = height; + _size_loaded = true; + updateSize(); } } @@ -1619,8 +1740,6 @@ void YellowNote::save() return; } - std::cout << "Saving " << _title << "..." << _size_loaded << ", " << _width << ", h = " << _height << std::endl; - std::filesystem::path p(_filename); FILE *f = fopen(_filename.c_str(), "wt"); if (f) { @@ -1631,6 +1750,7 @@ void YellowNote::save() fprintf(f, "%d\n", _width); fprintf(f, "%d\n", _height); fprintf(f, "%d\n", _color); + fprintf(f, "%d\n", _title_only); fprintf(f, "%s\n", _title.c_str()); GtkTextIter start, end; diff --git a/yellownotes.h b/yellownotes.h index be20dce..2ec54e1 100644 --- a/yellownotes.h +++ b/yellownotes.h @@ -10,7 +10,7 @@ extern "C" { } class YellowNote; -class ColorSet; +class SettingContainer; typedef enum { DARK = 0, @@ -33,7 +33,7 @@ private: void *_dlg; void *_langs; - std::list _color_sets; + std::list _settings_containers; std::list _notes; int _font_size; @@ -56,6 +56,8 @@ public: int fontSize(); int iconSize(); GtkWindow *topLevel(); + void colorSet(void *sender); + void setFontSize(int size); public: void popupTrayMenu(void *sender); @@ -83,11 +85,11 @@ public: void setBgColor(ColorType_t type, const std::string &col); std::string fromRGBA(const GdkRGBA &rgba); void toRGBA(const std::string &col, GdkRGBA &rgba); + void updateWidgetCss(GtkWidget *w, ColorType_t col); public: YellowNotes(void *app); ~YellowNotes(); - void colorSet(void *sender); }; #define YELLOWNOTES(obj) reinterpret_cast(obj) From c62a9c76109574ef36b7b6fa746f6eb24bcb9c0b Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Mon, 24 Nov 2025 21:27:05 +0100 Subject: [PATCH 5/6] on new note, make it 'loaded' --- yellownotes.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/yellownotes.cpp b/yellownotes.cpp index fa962e1..ee5c90a 100644 --- a/yellownotes.cpp +++ b/yellownotes.cpp @@ -153,6 +153,7 @@ public: public: void load(); void save(); + void setLoaded(); public: YellowNote(YellowNotes *notes, const std::string &filename); @@ -855,6 +856,7 @@ void YellowNotes::newNote(void *sender) YellowNote *note = new YellowNote(this, p.string()); _notes.push_back(note); + note->setLoaded(); note->show(); note->save(); } @@ -1226,6 +1228,15 @@ void YellowNote::showNote(GtkWidget *sender) show(); } +void YellowNote::setLoaded() +{ + _pos_loaded = true; + _hidden_loaded = true; + _title_only_loaded = true; + _size_loaded = true; + _in_transaction = false; +} + void YellowNote::show() { gtk_widget_show_all(_note_widget); From 4c10bb6b9f1d4086572cb3beed1ae95cc96e3c5b Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Mon, 24 Nov 2025 21:30:15 +0100 Subject: [PATCH 6/6] name of yellownotes turned around, makes it easier to monitor them --- yellownotes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yellownotes.cpp b/yellownotes.cpp index ee5c90a..1a3d9c0 100644 --- a/yellownotes.cpp +++ b/yellownotes.cpp @@ -835,7 +835,7 @@ void YellowNotes::newNote(void *sender) char buf[200]; int r = rand() % 1000; - sprintf(buf, "%llu-%d", milliseconds_since_epoch, r); + sprintf(buf, "%d-%llu", r, milliseconds_since_epoch); std::string new_note_file = buf; std::string notes_dir = notesDir();