283
yellownotes.cpp
283
yellownotes.cpp
@@ -13,6 +13,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <shobjidl.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
@@ -21,7 +22,9 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "tr.h"
|
||||
|
||||
#include "info_over_me.h"
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <math.h>
|
||||
|
||||
static void trim(std::string &s) {
|
||||
@@ -34,6 +37,17 @@ static void trim(std::string &s) {
|
||||
s = s.substr(start, end - start + 1);
|
||||
}
|
||||
|
||||
class StoredCoords
|
||||
{
|
||||
public:
|
||||
bool hidden;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
std::string os_host;
|
||||
};
|
||||
|
||||
|
||||
class YellowNote
|
||||
{
|
||||
@@ -65,6 +79,8 @@ private:
|
||||
std::string _note;
|
||||
std::string _title;
|
||||
|
||||
std::list<StoredCoords> _stored_coords;
|
||||
|
||||
bool _hidden;
|
||||
bool _hidden_loaded;
|
||||
|
||||
@@ -143,6 +159,7 @@ public:
|
||||
bool textSaveTimeout();
|
||||
bool windowPresented(void *sender, GdkEventVisibility *evt);
|
||||
void showNote(GtkWidget *sender);
|
||||
void moveTo(int x, int y);
|
||||
|
||||
public:
|
||||
std::string title();
|
||||
@@ -232,10 +249,12 @@ SIGNAL(YellowNotes, on_to_back, notesToDesktop);
|
||||
SIGNAL(YellowNotes, on_reload, reloadNotes);
|
||||
SIGNAL(YellowNotes, on_setup, setup);
|
||||
SIGNAL(YellowNotes, on_quit, quit)
|
||||
SIGNAL(YellowNotes, on_reorder, reOrder);
|
||||
SIGNAL(YellowNotes, on_hide_toplevel, topLevelHidden)
|
||||
SIGNAL(YellowNotes, on_setup_ok, setupClose);
|
||||
SIGNAL(YellowNotes, on_setup_close, setupCancel);
|
||||
BSIGNAL2(YellowNotes, on_setup_del, setupDel, void);
|
||||
SIGNAL(YellowNotes, on_monitors_changed, monitorsChanged);
|
||||
|
||||
|
||||
std::string YellowNotes::imageFile(const char *name)
|
||||
@@ -326,6 +345,11 @@ void YellowNotes::updateWidgetCss(GtkWidget *w, ColorType_t col)
|
||||
set_style(w);
|
||||
}
|
||||
|
||||
GtkWidget *YellowNotes::getWindow()
|
||||
{
|
||||
return topLevel();
|
||||
}
|
||||
|
||||
std::string YellowNotes::getFgColor(ColorType_t type)
|
||||
{
|
||||
char buf[100];
|
||||
@@ -496,6 +520,7 @@ void YellowNotes::popupTrayMenu(void *sender)
|
||||
GtkWidget *sep1 = gtk_separator_menu_item_new();
|
||||
|
||||
GtkMenuItem *setup = gtk_menu_item_new_with_label(_("Setup"));
|
||||
GtkMenuItem *reorder = gtk_menu_item_new_with_label(_("Reorder Notes"));
|
||||
GtkMenuItem *quit = gtk_menu_item_new_with_label(_("Quit"));
|
||||
|
||||
gtk_menu_shell_append(tray_menu, new_yellow);
|
||||
@@ -512,6 +537,7 @@ void YellowNotes::popupTrayMenu(void *sender)
|
||||
|
||||
gtk_menu_shell_append(tray_menu, sep1);
|
||||
gtk_menu_shell_append(tray_menu, setup);
|
||||
gtk_menu_shell_append(tray_menu, reorder);
|
||||
gtk_menu_shell_append(tray_menu, quit);
|
||||
gtk_widget_show_all(tray_menu);
|
||||
|
||||
@@ -520,6 +546,7 @@ void YellowNotes::popupTrayMenu(void *sender)
|
||||
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(reorder, "activate", on_reorder, this);
|
||||
g_signal_connect(quit, "activate", on_quit, this);
|
||||
w_it = hidden.begin();
|
||||
it = h_notes.begin();
|
||||
@@ -811,6 +838,22 @@ void YellowNotes::setup(void *sender)
|
||||
gtk_widget_show_all(dlg);
|
||||
}
|
||||
|
||||
void YellowNotes::reOrder(void *sender)
|
||||
{
|
||||
int x = 50;
|
||||
int y = 50;
|
||||
|
||||
std::list<YellowNote *>::iterator it;
|
||||
for(it = _notes.begin(); it != _notes.end(); it++, x += 25, y += 25) {
|
||||
(*it)->moveTo(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void YellowNotes::monitorsChanged(void *sender)
|
||||
{
|
||||
this->reloadNotes(sender);
|
||||
}
|
||||
|
||||
void YellowNotes::reloadNotes(void *sender)
|
||||
{
|
||||
std::list<YellowNote *>::const_iterator it = _notes.begin();
|
||||
@@ -911,6 +954,87 @@ void YellowNotes::topLevelHidden(GtkWidget *sender)
|
||||
g_timeout_add(500, show_notes_timed, this);
|
||||
}
|
||||
|
||||
void YellowNotes::checkMonitors()
|
||||
{
|
||||
auto compare = [](const Geom_t &a, const Geom_t &b) {
|
||||
if (a.x < b.x) {
|
||||
return true;
|
||||
} else if (a.x > b. x) {
|
||||
return false;
|
||||
} else if (a.y < b.y) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
GdkDisplay *d = gdk_display_get_default();
|
||||
int n = gdk_display_get_n_monitors(d);
|
||||
|
||||
if (_monitors.empty()) {
|
||||
int i;
|
||||
for(i = 0; i < n; i++) {
|
||||
GdkMonitor *m = gdk_display_get_monitor(d, i);
|
||||
GdkRectangle r;
|
||||
gdk_monitor_get_geometry(m, &r);
|
||||
Geom_t g;
|
||||
g.x = r.x;
|
||||
g.y = r.y;
|
||||
g.width = r.width;
|
||||
g.height = r.height;
|
||||
_monitors.push_back(g);
|
||||
}
|
||||
_monitors.sort(compare);
|
||||
} else {
|
||||
if (n != _monitors.size()) {
|
||||
_monitors.clear();
|
||||
checkMonitors();
|
||||
monitorsChanged(nullptr);
|
||||
} else {
|
||||
std::list<Geom_t> l;
|
||||
int i;
|
||||
for(i = 0; i < n; i++) {
|
||||
GdkMonitor *m = gdk_display_get_monitor(d, i);
|
||||
GdkRectangle r;
|
||||
gdk_monitor_get_geometry(m, &r);
|
||||
Geom_t g;
|
||||
g.x = r.x;
|
||||
g.y = r.y;
|
||||
g.width = r.width;
|
||||
g.height = r.height;
|
||||
l.push_back(g);
|
||||
}
|
||||
l.sort(compare);
|
||||
std::list<Geom_t>::iterator m_it = _monitors.begin();
|
||||
std::list<Geom_t>::iterator l_it = l.begin();
|
||||
while(l_it != l.end()) {
|
||||
Geom_t g_l = *l_it;
|
||||
Geom_t g_m = *m_it;
|
||||
if (g_l.x != g_m.x || g_l.y != g_m.y || g_l.width != g_m.width || g_l.height != g_m.height) {
|
||||
_monitors.clear();
|
||||
checkMonitors();
|
||||
monitorsChanged(nullptr);
|
||||
}
|
||||
l_it++;
|
||||
m_it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static YellowNotes *_the_notes = nullptr;
|
||||
|
||||
gboolean monitor_monitors(void *data)
|
||||
{
|
||||
YellowNotes *n = reinterpret_cast<YellowNotes *>(data);
|
||||
if (_the_notes == nullptr) {
|
||||
return false;
|
||||
} else {
|
||||
n->checkMonitors();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWindow *YellowNotes::topLevel()
|
||||
{
|
||||
if (_toplevel == nullptr) {
|
||||
@@ -927,11 +1051,14 @@ YellowNotes::YellowNotes(void *app)
|
||||
_tray_menu = nullptr;
|
||||
_font_size = 15;
|
||||
_toplevel = nullptr;
|
||||
_the_notes = this;
|
||||
g_timeout_add(1000, monitor_monitors, this); // Beware monitor_monitors checks _the_notes.
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
YellowNotes::~YellowNotes()
|
||||
{
|
||||
_the_notes = nullptr;
|
||||
if (_tray_menu) { gtk_widget_destroy(reinterpret_cast<GtkMenu *>(_tray_menu)); }
|
||||
clearNotes();
|
||||
gtk_widget_destroy(_toplevel);
|
||||
@@ -1228,6 +1355,13 @@ void YellowNote::showNote(GtkWidget *sender)
|
||||
show();
|
||||
}
|
||||
|
||||
void YellowNote::moveTo(int x, int y)
|
||||
{
|
||||
_x = x;
|
||||
_y = y;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
void YellowNote::setLoaded()
|
||||
{
|
||||
_pos_loaded = true;
|
||||
@@ -1299,12 +1433,20 @@ void YellowNote::toFront()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void YellowNote::toDesktop()
|
||||
{
|
||||
#ifdef __linux
|
||||
gtk_window_set_type_hint(_note_widget, GdkWindowTypeHint::GDK_WINDOW_TYPE_HINT_DESKTOP);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
GdkWindow *notes_win = gtk_widget_get_window(_notes->getWindow());
|
||||
HWND nw = gdk_win32_window_get_handle(notes_win);
|
||||
SetWindowPos(nw, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
|
||||
GdkWindow *win = gtk_widget_get_window(_note_widget);
|
||||
HWND w = gdk_win32_window_get_handle(win);
|
||||
SetWindowPos(w, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void YellowNote::fromDesktop()
|
||||
@@ -1655,7 +1797,7 @@ bool YellowNote::moving(GtkWidget *sender, GdkEventMotion *evt)
|
||||
return false;
|
||||
}
|
||||
|
||||
#define YELLOWNOTE_VERSION 2
|
||||
#define YELLOWNOTE_VERSION 3
|
||||
|
||||
void YellowNote::load()
|
||||
{
|
||||
@@ -1678,6 +1820,68 @@ void YellowNote::load()
|
||||
std::string title;
|
||||
bool title_only;
|
||||
|
||||
InfoOverMe info;
|
||||
std::string my_name = info.myId();
|
||||
|
||||
auto readKind = [my_name, this](std::string line, std::function<void (const std::string &os_host, int val)> f) {
|
||||
// Split line in parts.
|
||||
std::istringstream inp(line);
|
||||
std::string part;
|
||||
bool found = false;
|
||||
while(std::getline(inp, part, ',')) {
|
||||
std::string os_host;
|
||||
int val;
|
||||
int idx;
|
||||
idx = part.find(":");
|
||||
if (idx >= 0) {
|
||||
os_host = part.substr(0, idx);
|
||||
std::string s = part.substr(idx + 1);
|
||||
val = atoi(s.c_str());
|
||||
f(os_host,val);
|
||||
if (os_host == my_name) { found = true; }
|
||||
}
|
||||
}
|
||||
return found;
|
||||
};
|
||||
|
||||
auto getStoredCoord = [this](const std::string &os_host, bool &created) {
|
||||
std::list<StoredCoords>::iterator it = _stored_coords.begin();
|
||||
while(it != _stored_coords.end() && it->os_host != os_host) {
|
||||
it++;
|
||||
}
|
||||
if (it == _stored_coords.end()) {
|
||||
StoredCoords c;
|
||||
c.os_host = os_host;
|
||||
_stored_coords.push_back(c);
|
||||
StoredCoords *r = &(_stored_coords.back());
|
||||
created = true;
|
||||
return r;
|
||||
} else {
|
||||
StoredCoords *r = &(*it);
|
||||
created = false;
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
auto setStoredCoordVar = [this, getStoredCoord, readKind](std::string line, std::function<void(StoredCoords *c, int v)> f) {
|
||||
auto setter = [f, this, getStoredCoord](const std::string &os_name, int val) {
|
||||
bool created;
|
||||
StoredCoords *r = getStoredCoord(os_name, created);
|
||||
f(r, val);
|
||||
};
|
||||
readKind(line, setter);
|
||||
};
|
||||
|
||||
auto readLine = [](FILE *f) {
|
||||
char buf[10240];
|
||||
fgets(buf, 10240, f);
|
||||
std::string l(buf);
|
||||
trim(l);
|
||||
return l;
|
||||
};
|
||||
|
||||
_stored_coords.clear();
|
||||
|
||||
size_t s = 0;
|
||||
if (std::filesystem::is_regular_file(p)) {
|
||||
s = std::filesystem::file_size(p);
|
||||
@@ -1687,11 +1891,36 @@ void YellowNote::load()
|
||||
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);
|
||||
if (version <= 2) {
|
||||
hidden = readInt(f, -1);
|
||||
x = readInt(f, 200);
|
||||
y = readInt(f, 200);
|
||||
width = readInt(f, 300);
|
||||
height = readInt(f, 200);
|
||||
} else {
|
||||
// fill in the dots.
|
||||
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->hidden = val; });
|
||||
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->x = val; });
|
||||
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->y = val; });
|
||||
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->width = val; });
|
||||
setStoredCoordVar(readLine(f), [](StoredCoords *c, int val) { c->height = val; });
|
||||
|
||||
bool created;
|
||||
StoredCoords *r = getStoredCoord(my_name, created);
|
||||
if (created) {
|
||||
r->hidden = false;
|
||||
r->x = 100;
|
||||
r->y = 100;
|
||||
r->width = 300;
|
||||
r->height = 200;
|
||||
}
|
||||
|
||||
hidden = r->hidden;
|
||||
x = r->x;
|
||||
y = r->y;
|
||||
width = r->width;
|
||||
height = r->height;
|
||||
}
|
||||
|
||||
int color;
|
||||
color = readInt(f, ColorType_t::YELLOW);
|
||||
@@ -1751,15 +1980,43 @@ void YellowNote::save()
|
||||
return;
|
||||
}
|
||||
|
||||
InfoOverMe info;
|
||||
std::string my_name = info.myId();
|
||||
|
||||
auto storeKind = [my_name, this](int val, std::function<int (const StoredCoords &)> f) {
|
||||
std::string line("");
|
||||
std::list<StoredCoords>::iterator it;
|
||||
std::string comma("");
|
||||
bool stored = false;
|
||||
for(it = _stored_coords.begin(); it != _stored_coords.end(); it++) {
|
||||
const StoredCoords &c = *it;
|
||||
int num = (my_name == c.os_host) ? val : f(c);
|
||||
if (my_name == c.os_host) { stored = true; }
|
||||
char buf[100];
|
||||
sprintf(buf, "%d", num);
|
||||
line += comma + c.os_host + ":" + buf;
|
||||
comma = ",";
|
||||
}
|
||||
if (!stored) {
|
||||
char buf[100];
|
||||
sprintf(buf, "%d", val);
|
||||
line += comma + my_name + ":" + buf;
|
||||
}
|
||||
return line;
|
||||
};
|
||||
|
||||
std::filesystem::path p(_filename);
|
||||
FILE *f = fopen(_filename.c_str(), "wt");
|
||||
if (f) {
|
||||
fprintf(f, "%d\n", YELLOWNOTE_VERSION);
|
||||
fprintf(f, "%d\n", _hidden);
|
||||
fprintf(f, "%d\n", _x);
|
||||
fprintf(f, "%d\n", _y);
|
||||
fprintf(f, "%d\n", _width);
|
||||
fprintf(f, "%d\n", _height);
|
||||
|
||||
|
||||
fprintf(f, "%s\n", storeKind(_hidden, [](const StoredCoords &c) { return c.hidden; }).c_str());
|
||||
fprintf(f, "%s\n", storeKind(_x, [](const StoredCoords &c) { return c.x; }).c_str());
|
||||
fprintf(f, "%s\n", storeKind(_y, [](const StoredCoords &c) { return c.y; }).c_str());
|
||||
fprintf(f, "%s\n", storeKind(_width, [](const StoredCoords &c) { return c.width; }).c_str());
|
||||
fprintf(f, "%s\n", storeKind(_height, [](const StoredCoords &c) { return c.height; }).c_str());
|
||||
|
||||
fprintf(f, "%d\n", _color);
|
||||
fprintf(f, "%d\n", _title_only);
|
||||
fprintf(f, "%s\n", _title.c_str());
|
||||
|
||||
Reference in New Issue
Block a user