diff options
| author | Gaspar Fernandez <gaspar.fernandez@totaki.com> | 2016-08-12 01:29:28 +0200 |
|---|---|---|
| committer | Gaspar Fernandez <gaspar.fernandez@totaki.com> | 2016-08-12 01:29:28 +0200 |
| commit | e463cfd3cbd419dc38583fe25b93be36b330a606 (patch) | |
| tree | add192be35a2e37ace95ee6f33a0a65d612dad9b /src/dwgo.cpp | |
| parent | f5932870164b72d2a67352495f3062f31f1fc5fd (diff) | |
| download | dwgo-e463cfd3cbd419dc38583fe25b93be36b330a606.tar.gz dwgo-e463cfd3cbd419dc38583fe25b93be36b330a606.tar.bz2 dwgo-e463cfd3cbd419dc38583fe25b93be36b330a606.zip | |
Version 0.4d
Diffstat (limited to 'src/dwgo.cpp')
| -rw-r--r-- | src/dwgo.cpp | 1031 |
1 files changed, 1031 insertions, 0 deletions
diff --git a/src/dwgo.cpp b/src/dwgo.cpp new file mode 100644 index 0000000..623273d --- /dev/null +++ b/src/dwgo.cpp @@ -0,0 +1,1031 @@ + /******************************************************************************** + * File: wdgo.cpp * + * Version: 0.3 * + * Date: 20080508 * + * Author: Gaspar Fernández (helyo@totaki.com) * + * * + * Copyright (C) 2008 Gaspar Fernández * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + * * + ******************************************************************************** + * Description: + * It is a Window Maker dockapp wich fetches weather information of the + * selected cities from National Weather Service (http://weather.noaa.gov/) + * to display current temperature and chage background image depending on + * the current weather conditions. + * + * Change History: + * Date (D.M.Y) Author Modification + * 08.05.2008 Gaspar Fernández Initial release + * + ********************************************************************************/ + +#include <iostream> +#include <fstream> +#include <vector> +#include <string.h> +#include <strings.h> +#include <pthread.h> +#include <X11/Xlib.h> +#include <X11/xpm.h> +#include <X11/Xutil.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <pwd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <math.h> +#include <time.h> +#include <X11/XKBlib.h> + +#include "XDraw.h" +#include "errors.h" +#include "localtemp.h" +#include "dwgo.h" +#include "strutils.cpp" +#include "config.h" + +using namespace std; + +typedef struct +{ + vector <localtemp *> weathers; + bool loaded; + int refresh; // When timer reaches refresh it reloads the information + int counter; // Timer +} Wth_vector; + +typedef struct +{ + char station[5]; // Metar ID [ 4 characters + \0 + char name[16]; // Station name (it's for you). It's short to fit in. +} T_Station; + +typedef struct +{ + int x, y, z; +} T_Point; + +typedef struct +{ + char *img; // Xpm asociated + char *text_font; // Location text font + char *temp_font; // Temperature text font + char *time_font; // Temperature text font + XDraw::XDrawColor text_color; // Text color + XDraw::XDrawColor temp_color; // Temperature Color + XDraw::XDrawColor time_color; // Temperature Color + T_Point stname; // Where to put the station name + T_Point sttemp; // Where to put the temperature + T_Point sttime; // Where to put the temperature +} T_Theme; + +typedef struct +{ + int x1, x2, y1, y2; + XDraw::XDrawColor in_color, out_color, bar_color; +} T_WaitBox; + +typedef struct +{ + vector <T_Station> stations; // List of preferred stations + + T_Theme metar_themes[TOTAL_THEMES]; // Load themes preferences + T_WaitBox wbox; // Wait box + + int update_int; // Update interval + char deg_unit; // Celsius or Fahrenheit +} DwgoConf; + +/************************************************************* + * Function: fetchWeatherInfo * + ************************************************************* + * Description: * + * Fetch weather information from the server. It * + * downloads a file for every location in our vector. * + * * + * Input: * + * Wth_vector *weathers - Our weather vector * + * * + * Output: * + * Nothing * + * * + * Change History: * + * Date Author Modification * + * 20101106 Gaspar Fernández Added error status * + *************************************************************/ +void fetchWeatherInfo(Wth_vector *weathers) +{ + Wth_vector *wths= (Wth_vector *)weathers; + // bool allok=true; + for (unsigned int k=0; k<wths->weathers.size(); k++) { + localtemp *current = wths->weathers.at(k); + wths->loaded=false; // This will make animated bar disappear when loaded + + if (!current->getInfo()) + { + verbsth(VERB_WARNING, "Don't have access to the server... I'll try later"); + break; + } + else if (current->error) + { + verbsth(VERB_WARNING, "Got an error while retrieving information."); + break; + } + } + // wths->loaded=allok; // All loaded +} + +/************************************************************* + * Function: getWeatherInfo * + ************************************************************* + * Description: * + * Calls fetchWeatherInfo periodically * + * * + * Input: * + * voir *weathers - Our weather vector. It's a void type * + * because it is called using pthread_create. * + * * + * Output: * + * NULL * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void *getWeatherInfo(void *weathers) +{ + while (1) // Fetch periodically temperatures + { + if (((Wth_vector *)weathers)->counter>=((Wth_vector *)weathers)->refresh) + { + ((Wth_vector *)weathers)->counter=0; + fetchWeatherInfo((Wth_vector *)weathers); + } + sleep(1); + // fetchWeatherInfo((Wth_vector *)weathers); + ((Wth_vector *)weathers)->counter++; + } + return NULL; +} + +/************************************************************* + * Function: load_coords * + ************************************************************* + * Description: * + * Translates a string with a,b,c with a,b,c three ints * + * to a T_Point structure. But the string may contain two, * + * or one number. It is used to locate text, so X * + * coordinate, can wi CENTER_TEXT, and Z can be * + * DEFAULT_MAX_WIDTH * + * * + * Input: * + * a string with the coordinates separated with commas. * + * * + * Output: * + * T_Point structure containing x, y and z * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +T_Point load_coords(const string &str) +{ + T_Point coord; + size_t coma = str.find(',',0); // Finds comma + size_t coma2 = str.find(',', coma+1); // Finds another comma + coord.z = DEFAULT_MAX_WIDTH; + + if (coma!=string::npos) + { // Load coordinates + coord.x = atoi(trim(str.substr(0,coma)).data()); + if (coma2!=string::npos) + { + coord.z = atoi(trim(str.substr(coma+1, coma2-coma+1)).data()); + coord.y = atoi(trim(str.substr(coma2+1)).data()); + } + else + coord.y = atoi(trim(str.substr(coma+1)).data()); + } + else + { // Centers text in X + coord.x = CENTER_TEXT; + coord.y = atoi(str.data()); + } + + return coord; +} + +/************************************************************* + * Function: load_colors * + ************************************************************* + * Description: * + * Read the string containing red, green and blue values * + * for the desired colour separated with commas. And stores * + * this values in a XDrawColor structure * + * * + * Input: * + * string with r,g,b values * + * * * + * Output: * + * XDrawColor structure with that information * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +XDraw::XDrawColor load_colors(string str) +{ + XDraw::XDrawColor color; + sscanf(str.data(),"%d %d %d", &color.r, &color.g, &color.b); + return color; +} + +/************************************************************* + * Function: load_wbcoords * + ************************************************************* + * Description: * + * Made only to read from config. file the coords of the * + * upper left and lower right corners of the wait box * + * (this one that appears when the data is being downloaded)* + * * + * Input: * + * string with the coords. separated with spaces * + * T_WaitBox structure where to store the data * + * * + * Output: * + * inside T_WaitBox structure, the coordinates of the * + * box are loaded from the string * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void load_wbcoords(string str, T_WaitBox *wbox) +{ + sscanf(str.data(),"%d %d %d %d", &wbox->x1, &wbox->y1, &wbox->x2, &wbox->y2); +} + +bool existsfilepath(const char* path, const char* file, char pathfile[]) +{ + bzero(pathfile, 256); // Erase last data + strcpy(pathfile, path); + strcat((char*)pathfile, file); + return (file_exists(pathfile)); +} + +/************************************************************* + * Function: load_config * + ************************************************************* + * Description: * + * Loads the config file into the DwgoConf structure. * + * We also do some checks to return error codes. * + * * + * Input: * + * char* file - File to read the configuration * + * DwgoConf &config - Where to put the configuration * + * Display *display - Used to make some checks * + * * + * Output: * + * DwgoConf &config - We store here the configuration * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void load_config(const char *file, DwgoConf &config, Display *disp, const char *homedir) +{ + ifstream inFile; + + string temp,a,b,c,tmp; + char *other_dir; + char *datadir; + size_t pos, pos2; + T_Station station; + int aux; + char pathfile[256]; // 256 temp chars for path+file + // This array stores all themes, as we may read it in the file. + const char *theme_keywords[TOTAL_THEMES]={"default", "clear", "cloudy", "broken", "tcu", "rainy", "snowy", "hail", "foggy", "dust", "otparts"}; + cout<<homedir<<"*\n"; + other_dir=(char*)malloc(strlen(homedir)+6); strcpy(other_dir, homedir); strcat(other_dir, (char*)"/.dwgo"); + datadir =(char*)malloc(strlen(DATADIR)+5); strcpy(datadir, DATADIR); strcat(datadir, (char*)"/dwgo"); + config.stations.clear(); // Clear station vector + config.update_int=0; + config.deg_unit=DEFAULT_DEG_UNIT; + inFile.open(file) ; + +// verbsth(VERB_NOTICE, "K"+strcat((char*)homedir,(char*)file);); + if (inFile.is_open()) + { + while (!inFile.eof()){ + getline(inFile,temp); + pos = temp.find_first_of((char*)" =#"); // We can find \n (skipped when reading) , #, =, (space) symbols + if (pos!=string::npos) + { + a=trim(temp.substr(0,pos)); // Store here what's before the " ","=" of "#" + b=trim(temp.substr(pos+1)); // Store here what's after that + switch (temp[pos]) + { + case '=': // If we've found =... + pos2=a.find("->"); // An arrow indicates theme or waitbox properties + if (pos2!=string::npos) + { + c=a.substr(pos2+2); // Store here what's after the -> + a=a.substr(0,pos2); // Store here what's between the = and the -> + aux=find_str_in_array(a.data(),theme_keywords, TOTAL_THEMES); // if we've found a, in the array of themes... + if (aux>-1) // Right theme, let's see the options + { + if (c=="img") // img property, specify the XPM to load when this theme is active + { + tmp="/"+b; + if (file_exists(b.data())) + load_str_chr(&config.metar_themes[aux].img, b); + else if (existsfilepath(other_dir, tmp.data(), pathfile)) + load_str_chr(&config.metar_themes[aux].img, pathfile); + else if (existsfilepath(datadir, tmp.data(), pathfile)) + load_str_chr(&config.metar_themes[aux].img, pathfile); + else + verbsth(VERB_WARNING,"Can't find default img file: "+b+" for "+c+"_img attribute"); + } + else if (c=="txtfont") // text found - Generally station name + { + if (testfont(b.data(), disp)) + load_str_chr(&config.metar_themes[aux].text_font, b); + else + { + if (aux>0) + { + load_str_chr(&config.metar_themes[aux].text_font, config.metar_themes[0].text_font); // Load default font + verbsth(VERB_WARNING, ("Can't load font: ")+b+(" loading default instead.")); + } + else + error_handler(ERR_BADFONT, (char*) b.data()); // Can't continue + } + } + else if (c=="tempfont") // temperature font + { + if (testfont(b.data(), disp)) + load_str_chr(&config.metar_themes[aux].temp_font, b); + else + { + if (aux>0) + { + load_str_chr(&config.metar_themes[aux].temp_font, config.metar_themes[0].temp_font); // Load default font + verbsth(VERB_WARNING, ("Can't load font: ")+b+(" loading default instead.")); + } + else + error_handler(ERR_BADFONT, (char*) b.data()); // Can't continue + } + } + else if (c=="timefont") // time fond - Specify when was the data taken + { + if (testfont(b.data(), disp)) + load_str_chr(&config.metar_themes[aux].time_font, b); + else + { + if (aux>0) + { + load_str_chr(&config.metar_themes[aux].time_font, config.metar_themes[0].time_font); // Load default font + verbsth(VERB_WARNING, ("Can't load font: ")+b+(" loading default instead.")); + } + else + error_handler(ERR_BADFONT, (char*) b.data()); // Can't continue + } + + } + else if (c=="txtloc") // Where to put the station name text + config.metar_themes[aux].stname=load_coords(b); + else if (c=="timloc") // Where to put the time text + config.metar_themes[aux].sttime=load_coords(b); + else if (c=="tmploc") // Where to put the temperature text + config.metar_themes[aux].sttemp=load_coords(b); + else if (c=="textcolor") // Station name text color + config.metar_themes[aux].text_color=load_colors(b); + else if (c=="timecolor") // Time text color + config.metar_themes[aux].time_color=load_colors(b); + else if (c=="tempcolor") // Temperature textcolor + config.metar_themes[aux].temp_color=load_colors(b); + } + else if (a=="waitbox") // If it is not a theme, it may be the waitbox + { + if (c=="coords") // Coordinates + load_wbcoords(b, &config.wbox); + else if (c=="out_color") // Border color + config.wbox.out_color=load_colors(b); + else if (c=="in_color") // Fill in color + config.wbox.in_color=load_colors(b); + else if (c=="bar_color") // Moving bar color + config.wbox.bar_color=load_colors(b); + } + else + verbsth(VERB_WARNING, "Sorry, I can't recognise "+a+"_"+c+" attribute."); + } + else if (a=="update_interval") // Weather will update each (update_interval) seconds + config.update_int=atoi(b.data()); + else if (a=="deg_unit") // (C)elsius or (F)ahrenheit + config.deg_unit=b[0]; // Only first char + + break; + case ' ': // If the first thing we see is a " ", insead of a "=" + if (a== "AddStation") // Adds station to monitor + { + pos=b.find(":",0); // The stations must be specified with the station name, separated with ":" + a=b.substr(0,pos); + b=b.substr(pos+1); + strcpy(station.station,a.data()); + strcpy(station.name,b.substr(0,14).data()); // Just 15 characters + config.stations.push_back(station); + verbsth(VERB_NOTICE, "Add Station \""+a+"\" called \""+b+"\""); + } + break; + + } + } + } + inFile.close(); + + if (config.update_int==0) // Prevent update_interval from being zero + config.update_int=DEFAULT_UPDATE_INTERVAL; // If it is not defined, or 0, replace it with the default value + if (config.metar_themes[DEFAULT_THEME].sttemp.y==-1) // Temperature must be shown + error_handler(ERR_BADSTTEMP,NULL); + // Colors must have positive values + if (config.metar_themes[DEFAULT_THEME].text_color.r==-1) + error_handler(ERR_BADDFTCLR,NULL); + if (config.metar_themes[DEFAULT_THEME].time_color.r==-1) + error_handler(ERR_BADDFICLR,NULL); + if (config.metar_themes[DEFAULT_THEME].temp_color.r==-1) + error_handler(ERR_BADDFECLR,NULL); + + } + else + error_handler(ERR_CFGNOTFOUND,NULL); +} + +/************************************************************* + * Function: time_diff * + ************************************************************* + * Description: * + * Calculates local timezone time difference with GMT. * + * * + * Input: * + * Nothing * + * * + * Output: * + * int - Time difference in seconds (local_time-gmt_time)* + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +int time_diff () +{ + struct tm *local, *gmt; + int local_s, gmt_s; + time_t tmp; + + tmp = time(0); + gmt = gmtime(&tmp); + if (gmt->tm_yday==0) + gmt->tm_yday=366; + + gmt_s = gmt->tm_yday*86400+gmt->tm_hour*3600 + gmt->tm_min* 60 + gmt->tm_sec; + + tmp = time(0); + local = localtime(&tmp); + if (local->tm_yday==0) + local->tm_yday=366; + local_s = local->tm_yday*86400 + local->tm_hour*3600 + local->tm_min*60 + local->tm_sec; + + return (local_s-gmt_s); +} + +/************************************************************* + * Function: displaytemp * + ************************************************************* + * Description: * + * Draws an image inside the dockapp and renders text * + * with location name, temperature and time when the data * + * was taken. * + * * + * Input: * + * XDraw *image - Image which will be drawn in the * + * dockapp. * + * DwgoConf cfg - Configuration * + * localtemp local_stt - Local Station information * + * int tm_diff - Time difference (see time_diff() func.)* + * char *xpmthemes - XPM images to display * + * * + * Output: * + * Nothing * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void displaytemp(XDraw *image, const DwgoConf cfg, localtemp *local_stt, int tm_diff, char *xpm_themes[]) +{ + char tmp_disp[10]; // Aux to display temperature + char *txt_font; + char *tmp_font; + char *tim_font; + int theme=local_stt->theme; + XDraw::XDrawColor txcolor, ticolor, tecolor; + T_Point sttemp, sttext, sttime; + time_t time_taking; + struct tm *moment; + + // We load each xpm_themes image when it is needed. + if (xpm_themes[theme]==NULL) + { + if (file_exists(cfg.metar_themes[theme].img)) + { + XpmReadFileToBuffer(cfg.metar_themes[theme].img, &xpm_themes[theme]); + verbsth(VERB_NOTICE, (string)"Loading img. theme: "+cfg.metar_themes[theme].img); + } + else + { // If xpm file doesn't exists we load the default theme + local_stt->theme=DEFAULT_THEME; + theme=DEFAULT_THEME; + } + + } + + // We do some checks and we change theme details to default details when we can't use them. + // We copy this data to our temp string. If we are quick, themes can change and the app crash + if (cfg.metar_themes[theme].text_font!=NULL) + load_str_chr(&txt_font,cfg.metar_themes[theme].text_font); + else + load_str_chr(&txt_font,cfg.metar_themes[0].text_font); + + if (cfg.metar_themes[theme].temp_font!=NULL) + load_str_chr(&tmp_font,cfg.metar_themes[theme].temp_font); + else + load_str_chr(&tmp_font,cfg.metar_themes[0].temp_font); + + if (cfg.metar_themes[theme].time_font!=NULL) + load_str_chr(&tim_font,cfg.metar_themes[theme].time_font); + else + load_str_chr(&tim_font,cfg.metar_themes[0].time_font); + + // (C)elsius of (F)ahrenheit + if (cfg.deg_unit=='F') + sprintf(tmp_disp, "%d "DEG_SYMBOL"F", local_stt->fahrenheit); + else + sprintf(tmp_disp, "%d "DEG_SYMBOL"C", local_stt->celsius); + + image->replace_background(xpm_themes[theme]); // Load the background image + image->setWindowPixmapShaped(); + + // If y position of the text is -1 in the current theme, it will be replaced with default theme position. + // but the temperature. It will be if y<=-1 (if text or time y position is >-1 it won't be displayed) + sttemp=(cfg.metar_themes[theme].sttemp.y>-1)?cfg.metar_themes[theme].sttemp:cfg.metar_themes[0].sttemp; + sttext=(cfg.metar_themes[theme].stname.y==-1)?cfg.metar_themes[DEFAULT_THEME].stname:cfg.metar_themes[theme].stname; + sttime=(cfg.metar_themes[theme].sttime.y==-1)?cfg.metar_themes[DEFAULT_THEME].sttime:cfg.metar_themes[theme].sttime; + + // Test current theme color + // If red value of the color is -1, the color will be replaced with the default. + txcolor=(cfg.metar_themes[theme].text_color.r==-1)?cfg.metar_themes[DEFAULT_THEME].text_color:cfg.metar_themes[theme].text_color; + ticolor=(cfg.metar_themes[theme].time_color.r==-1)?cfg.metar_themes[DEFAULT_THEME].time_color:cfg.metar_themes[theme].time_color; + tecolor=(cfg.metar_themes[theme].temp_color.r==-1)?cfg.metar_themes[DEFAULT_THEME].temp_color:cfg.metar_themes[theme].temp_color; + + // Draw strings + image->drawString(sttemp.x, sttemp.y, sttemp.z, tecolor, (char*)tmp_font, tmp_disp); + if (sttext.y>-1) + image->drawString(sttext.x, sttext.y, sttext.z, txcolor, (char*)txt_font, (char*)local_stt->location_name.data()); + if ((sttime.y>-1) && (local_stt->loaded)) + { + time_taking=local_stt->info_time+tm_diff; // Translates to local time + moment=localtime(&time_taking); + sprintf(tmp_disp, "%.2d:%.2d", moment->tm_hour,moment->tm_min); // Makes it 00:00 + image->drawString(sttime.x, sttime.y, sttime.z, ticolor, (char*)tim_font, (char*)tmp_disp); + } + + image->Sync(); + +} + +/************************************************************* + * Function: config_defaults * + ************************************************************* + * Description: * + * Loads the default configuration in DwgoConf structure.* + * * + * * + * Input: * + * DwgoConf *Dwgo_Configuration * + * * + * Output: * + * DwgoConf *Dwgo_Configuration - It will have defaults * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void config_defaults(DwgoConf *Dwgo_Configuration) +{ + const T_Point def_sttemp = DEFAULT_STTEMP; + const XDraw::XDrawColor clnull = DEFAULT_STTEMP; + + Dwgo_Configuration->wbox.x1=2; + Dwgo_Configuration->wbox.x2=62; + Dwgo_Configuration->wbox.y1=2; + Dwgo_Configuration->wbox.y1=12; + Dwgo_Configuration->wbox.in_color=setDrawColor(100,100,20); + Dwgo_Configuration->wbox.out_color=setDrawColor(10,10,2); + Dwgo_Configuration->wbox.bar_color=setDrawColor(50,50,12); + + for (int j=0;j<TOTAL_THEMES;j++) + { + Dwgo_Configuration->metar_themes[j].text_font=NULL; + Dwgo_Configuration->metar_themes[j].temp_font=NULL; + Dwgo_Configuration->metar_themes[j].time_font=NULL; + Dwgo_Configuration->metar_themes[j].sttemp=def_sttemp; + Dwgo_Configuration->metar_themes[j].stname=def_sttemp; + Dwgo_Configuration->metar_themes[j].sttime=def_sttemp; + Dwgo_Configuration->metar_themes[j].text_color=clnull; + Dwgo_Configuration->metar_themes[j].temp_color=clnull; + Dwgo_Configuration->metar_themes[j].time_color=clnull; + } + +} + +/************************************************************* + * Function: weathers_create_list * + ************************************************************* + * Description: * + * Fills the Wth_vector weathers vector with the * + * stations loaded from the confiuration file. And flag * + * the structure to update. * + * * + * Input: * + * Wth_vector *weathers - * + * DwgoConf Dwgo_Configuration - Where to get the data from* + * * + * Output: * + * Wth_vector - We will fill in the weathers vector here. * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void weathers_create_list(Wth_vector *weathers, DwgoConf Dwgo_Configuration) +{ + weathers->counter=Dwgo_Configuration.update_int; // Refresh now !! + weathers->refresh=Dwgo_Configuration.update_int; // Refresh now !! + + + weathers->loaded=false; + weathers->weathers.clear(); + + for (unsigned int k=0; k<Dwgo_Configuration.stations.size(); k++) + weathers->weathers.push_back(new localtemp((char*)Dwgo_Configuration.stations.at(k).station, + (char*)Dwgo_Configuration.stations.at(k).name)); + +} + +/************************************************************* + * Function: weathers_loader * + ************************************************************* + * Description: * + * Calls weathers_create_list and creates the thread * + * that will periodically reload weather information from * + * the server * + * * + * Input: * + * Wth_vector - Where the weather info will be stored * + * DwgoConf Dwgo_Configuration - Configuration loaded from * + * file * + * * + * Output: * + * Nothing * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +void weathers_loader(Wth_vector *weathers, DwgoConf Dwgo_Configuration) +{ + Wth_vector *th_parm; + pthread_t *threads; + pthread_attr_t pthread_custom_attr; + + weathers_create_list(weathers, Dwgo_Configuration); + + threads=(pthread_t *)malloc(1*sizeof(*threads)); + pthread_attr_init(&pthread_custom_attr); + + th_parm=weathers; + + pthread_create(threads, &pthread_custom_attr, getWeatherInfo, (void *)(th_parm)); +} + +/************************************************************* + * Function: getHomeDir * + ************************************************************* + * Description: * + * Try to guess home directory. First searching HOME * + * environment variable, then try getpwuid. * + * * + * Input: * + * Nothing * + * * + * Output: * + * char* path to user home * + * * + * Change History: * + * Date Author Modification * + * * + *************************************************************/ +char *getHomeDir() +{ + static char *home = NULL; + + if (!home) + { + home = getenv("HOME") ; + } + if (!home) + { + struct passwd *pw = getpwuid(getuid()); + if (pw) home = pw->pw_dir ; + } + return home; +} + +bool copyfile(const char* filefrom, const char* fileto) +{ + + FILE *ffrom = NULL; + FILE *fto = NULL; + char buf[512]; + + ffrom = fopen( filefrom, "rb" ); + if( ffrom != NULL ) + { + fto = fopen( fileto, "wb" ); + if( fto != NULL ) + { + while (fgets(buf, 256, ffrom)) { + if (fputs(buf, fto) == EOF) { // error writing data + return false; + } + } + } + else + return false; + + fclose( ffrom ); + } + else + return false; + return true; + +} + +char *locateConfig(const char* homeuser) +{ + static char cfgpath[256]; + char tmp[256]; + if (existsfilepath(homeuser, "/.dwgo.conf", cfgpath)) + return cfgpath; + else if (existsfilepath(homeuser, "/.dwgo/dwgo.conf", cfgpath)) + return cfgpath; + else if (existsfilepath(DATADIR, "/dwgo/dwgo.conf", cfgpath)) + { + existsfilepath(homeuser, "/.dwgo.conf", tmp); + if (copyfile(cfgpath, tmp)) // Copies /usr/share/dwgo/dwgo.conf -> ~/.dwgo.conf + strcpy(cfgpath, tmp); // If config file is copied -> Return user configuration + + return cfgpath; + } + else if (file_exists("dwgo.conf")) + return (char*)"dwgo.conf"; + else + return NULL; +} + +// Main application +int main(int argc, char** argv) { + + Wth_vector weathers; + + Display* disp; + Window mRoot; + Window mAppWin; + Window mIconWin; + char* xpm_themes[TOTAL_THEMES]; // Where to load XPMs + bool bar=false; // Toggle the bar beacuse you like it + XClassHint classHint; + XSizeHints sizeHints; + XWMHints wmHints; + Atom deleteWindow; + XDraw* image; + XEvent report; + KeySym ksym; + DwgoConf Dwgo_Configuration; // Main configuration + int eventmask; + + char *user_homedir; // User home directory + + char *home_dir; // Copy of user_homedir because we overwrite user_homedir Q&D + + char *config_path; // Config file with path + + int anim=0; // Waitbar animation status + bool direc=true; // Direction of the waitbar animation + + int punter=0; // Location being displayed actually + + int tm_diff=0; // Time differente + timespec tmp={0,30000000L}; // Sleep time between X updates + + user_homedir= getHomeDir(); + home_dir=(char*)malloc(strlen(user_homedir)); + strcpy(home_dir, user_homedir); + + config_path=locateConfig(user_homedir); + if (config_path==NULL) + error_handler(ERR_NOCFGFILE, NULL); + + if ((disp = XOpenDisplay(NULL)) == NULL) + error_handler(ERR_NODISPLAY, NULL); + + config_defaults(&Dwgo_Configuration); + for (int j=0;j<TOTAL_THEMES;j++) + xpm_themes[j]=NULL; // Point all xpms to NULL + + load_config(config_path, Dwgo_Configuration, disp, home_dir); + + tm_diff=time_diff(); + weathers_loader(&weathers, Dwgo_Configuration); + + + // Get root window + mRoot = RootWindow(disp, DefaultScreen(disp)); + // Create windows + mAppWin = XCreateSimpleWindow(disp, mRoot, 1, 1, 64, 64, 0, 0, 0); + mIconWin = XCreateSimpleWindow(disp, mAppWin, 0, 0, 64, 64, 0, 0, 0); + + // Set classhint + classHint.res_name = (char*) "DWGO"; + classHint.res_class = (char*) "DWGO"; + XSetClassHint(disp, mAppWin, &classHint); + + + // Create delete atom + deleteWindow = XInternAtom(disp, "WM_DELETE_WINDOW", False); + XSetWMProtocols(disp, mAppWin, &deleteWindow, 1); + XSetWMProtocols(disp, mIconWin, &deleteWindow, 1); + + // Set windowname + XStoreName(disp, mAppWin, "DWGO 0.3"); + XSetIconName(disp, mAppWin, "DWGO 0.3"); + + // Set sizehints + sizeHints.flags= USPosition; + sizeHints.x = 0; + sizeHints.y = 0; + XSetWMNormalHints(disp, mAppWin, &sizeHints); + // Set wmhints.. Make it a dockapp + wmHints.initial_state = WithdrawnState; + wmHints.icon_window = mIconWin; + wmHints.icon_x = 0; + wmHints.icon_y = 0; + wmHints.window_group = mAppWin; + wmHints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint; + XSetWMHints(disp, mAppWin, &wmHints); + + // Set command + XSetCommand(disp, mAppWin, argv, argc); // X Params. +// // Set background image + + XpmReadFileToBuffer(Dwgo_Configuration.metar_themes[DEFAULT_THEME].img, &xpm_themes[DEFAULT_THEME]); + image = new XDraw(disp, mRoot, xpm_themes[DEFAULT_THEME]); + image->setDefaultWindow(mIconWin); + image->setWindowPixmapShaped(mIconWin); + + XMapWindow(disp, mIconWin); + XMapWindow(disp, mAppWin); + XSync(disp, False); + + eventmask= ButtonPressMask | //ButtonReleaseMask | + FocusChangeMask | LeaveWindowMask | KeyPressMask | + EnterWindowMask; + XSelectInput(disp, mIconWin, eventmask ); + + while (1) // Main loop!! + { + if (XCheckMaskEvent(disp, eventmask, &report)) + { + switch (report.type) + { + case KeyPress: + ksym = XLookupKeysym(&(report.xkey), report.xkey.state); + + switch (ksym) + { +// case XK_Escape: +// exit(0); +// break; + case XK_F5: + if (weathers.counter>3) // Min. time between refreshes + weathers.counter=weathers.refresh; // Refresh weathers + else + verbsth(VERB_WARNING,"You just have updated temperatures!!! Wait a little bit!"); + break; + case XK_F6: // Reload conf. file, Useful form theme creation and conf. checks + punter=0; + weathers.counter=0; // Make sure it won't update during reload + config_defaults(&Dwgo_Configuration); + for (int j=0;j<TOTAL_THEMES;j++) + xpm_themes[j]=NULL; // Point all xpms to NULL + + load_config(".dwgo", Dwgo_Configuration, disp, home_dir); + weathers_create_list(&weathers, Dwgo_Configuration); + break; + case XK_Down: + case XK_Left: + punter--; + if (punter==-1) + punter=weathers.weathers.size()-1; + displaytemp(image, Dwgo_Configuration, weathers.weathers.at(punter), tm_diff, xpm_themes); + break; + case XK_Up: + case XK_Right: + punter++; + if ((unsigned)punter==weathers.weathers.size()) + punter=0; + displaytemp(image, Dwgo_Configuration, weathers.weathers.at(punter), tm_diff, xpm_themes); + break; + case XK_b: + bar=!bar; + displaytemp(image, Dwgo_Configuration, weathers.weathers.at(punter), tm_diff, xpm_themes); + + default: break; + + } + break; + case ButtonPress: + switch (report.xbutton.button) { + case Button1: + punter++; + if ((unsigned)punter==weathers.weathers.size()) + punter=0; + displaytemp(image, Dwgo_Configuration, weathers.weathers.at(punter), tm_diff, xpm_themes); + break; + case Button3: + verbsth(VERB_ASTTO,"Right click"); + break; + } + break; + case EnterNotify: + case LeaveNotify: + XSetInputFocus(disp, mIconWin, RevertToParent, CurrentTime); + verbsth(VERB_ASTTO, " Focus Change"); + break; + default: + verbsth(VERB_ASTTO, "Another Event"); + } + } + else + { + + if ((!weathers.weathers.at(punter)->loaded) || (bar)) + { + image->DrawRect(Dwgo_Configuration.wbox.x1,Dwgo_Configuration.wbox.y1,Dwgo_Configuration.wbox.x2,Dwgo_Configuration.wbox.y2, Dwgo_Configuration.wbox.out_color); + image->DrawRect(Dwgo_Configuration.wbox.x1+1,Dwgo_Configuration.wbox.y1+1,Dwgo_Configuration.wbox.x2-2,Dwgo_Configuration.wbox.y2-2, Dwgo_Configuration.wbox.in_color); + image->DrawRect(Dwgo_Configuration.wbox.x1+1+anim,Dwgo_Configuration.wbox.y1+1,6,Dwgo_Configuration.wbox.y2-2, Dwgo_Configuration.wbox.bar_color); + if (direc) + anim++; + else + anim--; + if ((anim==Dwgo_Configuration.wbox.x2-8) || (anim==0)) // Dwgo_Configuration.wbox.x2 -2 -6 (bar width) + direc=!direc; + image->Sync(); + } + else if (!weathers.loaded) + { + weathers.loaded=true; + displaytemp(image, Dwgo_Configuration, weathers.weathers.at(punter), tm_diff, xpm_themes); + } + + + } + nanosleep(&tmp, NULL); + } + delete image; +} |
