Logo Search packages:      
Sourcecode: cairo-dock-plugins version File versions  Download package

applet-dnd2share.c

/**
* This file is a part of the Cairo-Dock project
*
* Copyright : (C) see the 'copyright' file.
* E-mail    : see the 'copyright' file.
*
* 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/>.
*/

#include <string.h>
#include <stdlib.h>
#include <glib/gstdio.h>

#include "applet-struct.h"
#include "applet-dnd2share.h"


void cd_dnd2share_free_uploaded_item (CDUploadedItem *pItem)
{
      if (pItem == NULL)
            return ;
      g_strfreev (pItem->cDistantUrls);
      g_free (pItem->cItemName);
      g_free (pItem->cLocalPath);
      g_free (pItem);
}


void cd_dnd2share_build_history (void)
{
      gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
      GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
      if (pKeyFile == NULL)  // pas encore d'historique.
      {
            g_free (cConfFilePath);
            return ;
      }
      
      CDUploadedItem *pItem;
      gsize length = 0;
      gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
      int iSiteID, iFileType;
      gchar *cItemName;
      GString *sUrlKey = g_string_new ("");
      GError *erreur = NULL;
      int i,j;
      for (i = 0; pGroupList[i] != NULL; i ++)
      {
            cItemName = pGroupList[i];
            iSiteID = g_key_file_get_integer (pKeyFile, cItemName, "site", &erreur);
            if (erreur != NULL)
            {
                  cd_warning (erreur->message);
                  g_error_free (erreur);
                  erreur = NULL;
                  continue;
            }
            if (iSiteID >= CD_NB_SITES)
            {
                  cd_warning ("dnd2share : this backend doesn't exist !");
                  continue;
            }
            iFileType = g_key_file_get_integer (pKeyFile, cItemName, "type", &erreur);
            if (erreur != NULL)
            {
                  cd_warning (erreur->message);
                  g_error_free (erreur);
                  erreur = NULL;
                  continue;
            }
            if (iFileType >= CD_NB_FILE_TYPES)
            {
                  cd_warning ("dnd2share : this type of file doesn't exist !");
                  continue;
            }
            
            pItem = g_new0 (CDUploadedItem, 1);
            pItem->cItemName = cItemName;
            pItem->iSiteID = iSiteID;
            pItem->iFileType = iFileType;
            pItem->cDistantUrls = g_new0 (gchar*, myData.backends[iFileType][iSiteID].iNbUrls+1);
            for (j = 0; j < myData.backends[iFileType][iSiteID].iNbUrls; j ++)
            {
                  g_string_printf (sUrlKey, "url%d", j);
                  pItem->cDistantUrls[j] = g_key_file_get_string (pKeyFile, cItemName, sUrlKey->str, NULL);
            }
            pItem->iDate = g_key_file_get_integer (pKeyFile, cItemName, "date", NULL);  /// un 'int' est-ce que ca suffit ?...
            
            pItem->cLocalPath = g_key_file_get_string (pKeyFile, cItemName, "local path", NULL);
            pItem->cFileName = g_path_get_basename (pItem->cLocalPath);
            
            myData.pUpoadedItems = g_list_prepend (myData.pUpoadedItems, pItem);
      }
      g_string_free (sUrlKey, TRUE);
      g_free (pGroupList);  // le contenu a ete pris par la liste.
      g_key_file_free (pKeyFile);
}

void cd_dnd2share_clear_history (void)
{
      g_list_foreach (myData.pUpoadedItems, (GFunc) cd_dnd2share_free_uploaded_item, NULL);
      g_list_free (myData.pUpoadedItems);
      myData.pUpoadedItems = NULL;
}



static void _cd_dnd2share_threaded_upload (gchar *cFilePath)
{
      CDSiteBackend *pCurrentBackend = myData.pCurrentBackend[myData.iCurrentFileType];
      g_return_if_fail (pCurrentBackend != NULL);
      pCurrentBackend->upload (cFilePath);
}
static gboolean _cd_dnd2share_update_from_result (gchar *cFilePath)
{
      CD_APPLET_ENTER;
      if (myData.cResultUrls == NULL)  // une erreur s'est produite.
      {
            cairo_dock_remove_dialog_if_any (myIcon);
            cairo_dock_show_temporary_dialog_with_icon (D_("Couldn't upload the file, check that your internet connexion is active."),
                  myIcon,
                  myContainer,
                  myConfig.dTimeDialogs,
                  MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
      }
      else
      {
            CDSiteBackend *pCurrentBackend = myData.pCurrentBackend[myData.iCurrentFileType];
            // On rajoute l'item a l'historique.
            if (myConfig.iNbItems != 0)
            {
                  // On ouvre le fichier de l'historique.
                  gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
                  GKeyFile *pKeyFile;
                  if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))  // pas encore d'historique.
                        pKeyFile = g_key_file_new ();
                  else
                        pKeyFile = cairo_dock_open_key_file (cConfFilePath);
                  if (pKeyFile == NULL)  // probleme de droit ?
                  {
                        cd_warning ("Couldn't add this item to history.");
                  }
                  else
                  {
                        // On regarde si on n'a pas atteint la limite de taille de l'historique.
                        gsize length = 0;
                        gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
                        if (length == myConfig.iNbItems)  // il faut supprimer le 1er item.
                        {
                              g_key_file_remove_group (pKeyFile, pGroupList[0], NULL);
                              if (myData.pUpoadedItems != NULL)  // il est en dernier dans la liste.
                              {
                                    GList *it = g_list_last (myData.pUpoadedItems);
                                    if (it->prev != NULL)
                                          it->prev->next = NULL;
                                    it->prev = NULL;
                                    cd_dnd2share_free_uploaded_item (it->data);
                                    g_list_free1 (it);
                              }
                        }
                        g_strfreev (pGroupList);
                        
                        // on rajoute le nouvel item en fin de fichier.
                        time_t iDate = time (NULL);
                        gchar *cItemName = g_strdup_printf ("item_%ld", iDate);
                        
                        g_key_file_set_integer (pKeyFile, cItemName, "site", myConfig.iPreferedSite[myData.iCurrentFileType]);
                        g_key_file_set_integer (pKeyFile, cItemName, "date", iDate);  // idem que precedemment sur l'integer.
                        g_key_file_set_integer (pKeyFile, cItemName, "type", myData.iCurrentFileType);
                        GString *sUrlKey = g_string_new ("");
                        int j;
                        for (j = 0; j < pCurrentBackend->iNbUrls; j ++)
                        {
                              g_string_printf (sUrlKey, "url%d", j);
                              g_key_file_set_string (pKeyFile, cItemName, sUrlKey->str, myData.cResultUrls[j]);
                        }
                        g_key_file_set_string (pKeyFile, cItemName, "local path", cFilePath);
                        
                        // et en debut de liste aussi.
                        CDUploadedItem *pItem = g_new0 (CDUploadedItem, 1);
                        pItem->cItemName = cItemName;
                        pItem->iSiteID = myConfig.iPreferedSite[myData.iCurrentFileType];
                        pItem->iFileType = myData.iCurrentFileType;
                        pItem->cDistantUrls = g_new0 (gchar*, pCurrentBackend->iNbUrls + 1);
                        for (j = 0; j < pCurrentBackend->iNbUrls; j ++)
                        {
                              pItem->cDistantUrls[j] = g_strdup (myData.cResultUrls[j]);
                        }
                        pItem->iDate = iDate;
                        pItem->cLocalPath = g_strdup (cFilePath);
                        pItem->cFileName = g_path_get_basename (cFilePath);
                        myData.pUpoadedItems = g_list_prepend (myData.pUpoadedItems, pItem);
                        
                        // On ecrit tout.
                        cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
                        g_key_file_free (pKeyFile);
                        g_string_free (sUrlKey, TRUE);
                        
                        // On garde une copie du fichier.
                        if (myConfig.bkeepCopy && myData.iCurrentFileType == CD_TYPE_IMAGE)
                        {
                              gchar *cCommand = g_strdup_printf ("cp '%s' '%s/%s'", cFilePath, myData.cWorkingDirPath, cItemName);
                              int r = system (cCommand);
                              g_free (cCommand);
                        }
                  }
                  g_free (cConfFilePath);
            }
            
            // On copie l'URL dans le clipboard.
            gchar *cURL = myData.cResultUrls[pCurrentBackend->iPreferedUrlType];
            if (cURL == NULL)
            {
                  int i;
                  for (i = 0; i < pCurrentBackend->iNbUrls && cURL == NULL; i ++)
                  {
                        cURL = myData.cResultUrls[i];
                  }
            }
            cd_dnd2share_copy_url_to_clipboard (cURL);
            
            // On garde en memoire la derniere URL au cas ou on n'aurait pas/plus d'historique.
            g_free (myData.cLastURL);
            myData.cLastURL = g_strdup (cURL);
            myData.iCurrentItemNum = 0;
            
            // On signale par un dialogue la fin de l'upload.
            if (myConfig.bEnableDialogs || myDesklet)
            {
                  cairo_dock_remove_dialog_if_any (myIcon);
                  cairo_dock_show_temporary_dialog_with_icon (D_("File has been uploaded.\nJust press CTRL+v to paste its URL anywhere."),
                        myIcon,
                        myContainer,
                        myConfig.dTimeDialogs,
                        MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
            }
            
            // on met l'image correspondante sur l'icone.
            if (myConfig.bDisplayLastImage)
            {
                  if (myData.iCurrentFileType == CD_TYPE_IMAGE)
                        CD_APPLET_SET_IMAGE_ON_MY_ICON (cFilePath);
                  else
                        CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
                  //CD_APPLET_REDRAW_MY_ICON;
            }
      }
      
      // On arrete son animation.
      cairo_dock_stop_icon_animation (myIcon);
      CD_APPLET_REDRAW_MY_ICON;  // pour ne pas s'arreter au milieu de l'animation.
      
      // On nettoie la memoire partagee.
      cairo_dock_free_task (myData.pTask);
      myData.pTask = NULL;
      g_free (myData.cCurrentFilePath);
      myData.cCurrentFilePath = NULL;
      if (myData.cResultUrls)
            g_strfreev (myData.cResultUrls);
      myData.cResultUrls = NULL;
      if (myData.cTmpFilePath != NULL)
      {
            g_remove (myData.cTmpFilePath);
            g_free (myData.cTmpFilePath);
            myData.cTmpFilePath = NULL;
      }
      CD_APPLET_LEAVE (FALSE);
      //return FALSE;
}
void cd_dnd2share_launch_upload (const gchar *cFilePath, CDFileType iFileType)
{
      if (myData.pTask != NULL)
      {
            cd_warning ("Please wait the current upload is finished before starting a new one.");
            cairo_dock_remove_dialog_if_any (myIcon);
            cairo_dock_show_temporary_dialog_with_icon (D_("Please wait the current upload is finished before starting a new one."),
                  myIcon,
                  myContainer,
                  myConfig.dTimeDialogs,
                  MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
            return ;
      }
      
      if (myData.pCurrentBackend[iFileType]->upload == NULL)
      {
            cd_warning ("sorry, it's still not possible to upload this type of file");
            return ;
      }
      
      // on lance la mesure.
      if (strncmp (cFilePath, "file://", 7) == 0)
            cFilePath += 7;
      myData.cCurrentFilePath = g_strdup (cFilePath);  // sera efface a la fin de l'upload.
      myData.iCurrentFileType = iFileType;
      myData.pTask = cairo_dock_new_task (0,  // 1 shot task.
            (CairoDockGetDataAsyncFunc) _cd_dnd2share_threaded_upload,
            (CairoDockUpdateSyncFunc) _cd_dnd2share_update_from_result,
            myData.cCurrentFilePath);
      
      cairo_dock_launch_task (myData.pTask);
      
      // On lance une animation.
      cairo_dock_request_icon_animation (myIcon, myContainer, myConfig.cIconAnimation, 1e6);  // on l'interrompra nous-memes a la fin de l'upload.
      cairo_dock_mark_icon_as_clicked (myIcon);  // pour ne pas se faire interrompre par un survol.
      cairo_dock_launch_animation (myContainer);
}



void cd_dnd2share_clear_working_directory (void)
{
      g_return_if_fail (myData.cWorkingDirPath != NULL && *myData.cWorkingDirPath == '/');
      gchar *cCommand = g_strdup_printf ("rm -rf '%s'/*", myData.cWorkingDirPath);
      int r = system (cCommand);
      g_free (cCommand);
      
      gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
      g_file_set_contents (cConfFilePath, "#dnd2share's history\n\n", -1, NULL);
      g_free (cConfFilePath);
      
      if (myConfig.bDisplayLastImage)
      {
            CD_APPLET_SET_LOCAL_IMAGE_ON_MY_ICON (MY_APPLET_ICON_FILE);
      }
}


void cd_dnd2share_clear_copies_in_working_directory (void)
{
      g_return_if_fail (myData.cWorkingDirPath != NULL && *myData.cWorkingDirPath == '/');
      gchar *cCommand = g_strdup_printf ("find '%s' -mindepth 1 ! -name *.conf -exec rm -f '{}' \\;", myData.cWorkingDirPath);
      int r = system (cCommand);
      g_free (cCommand);
}

void cd_dnd2share_set_working_directory_size (int iNbItems)
{
      gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
      GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
      if (pKeyFile == NULL)  // pas encore d'historique.
      {
            g_free (cConfFilePath);
            return ;
      }
      
      gsize length = 0;
      gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
      if (length > iNbItems)
      {
            gchar *cItemName;
            GString *sPreviewPath = g_string_new ("");
            int i;
            for (i = 0; pGroupList[i] != NULL && i < length - iNbItems; i ++)  // on supprime les n premiers groupes en trop, ainsi que leurs eventuelles prevues.
            {
                  cItemName = pGroupList[i];
                  g_string_printf (sPreviewPath, "%s/%s", myData.cWorkingDirPath, cItemName);
                  g_remove (sPreviewPath->str);
                  g_key_file_remove_group (pKeyFile, cItemName, NULL);
            }
            cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
            g_string_free (sPreviewPath, TRUE);
      }
      
      g_strfreev (pGroupList);
      g_key_file_free (pKeyFile);
      g_free (cConfFilePath);
}

void cd_dnd2share_clean_working_directory (void)
{
      if (myConfig.iNbItems == 0)  // on ne veut plus d'historique => vidons le repertoire.
      {
            cd_debug ("DND2SHARE : Pas d'historique -> On efface le contenu de '%s'", myData.cWorkingDirPath);
            cd_dnd2share_clear_working_directory ();
      }
      else
      {
            cd_dnd2share_set_working_directory_size (myConfig.iNbItems);  // on efface les items en trop.
            if (! myConfig.bkeepCopy)  // on veut bien un historique mais sans les sauvegardes locales des images => nettoyons le repertoire.
            {
                  cd_debug ("DND2SHARE : Pas de copies locales -> On efface les images de '%s'", myData.cWorkingDirPath);
                  cd_dnd2share_clear_copies_in_working_directory ();
            }
      }
}


void cd_dnd2share_copy_url_to_clipboard (const gchar *cURL)
{
      GtkClipboard *pClipBoard;
      pClipBoard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
      gtk_clipboard_set_text (pClipBoard, cURL, -1);
}
void cd_dnd2share_copy_url_to_primary (const gchar *cURL)
{
      GtkClipboard *pClipBoard;
      pClipBoard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
      gtk_clipboard_set_text (pClipBoard, cURL, -1);
}

gchar *cd_dnd2share_get_prefered_url_from_item (CDUploadedItem *pItem)
{
      CDSiteBackend *pBackend = &myData.backends[pItem->iFileType][pItem->iSiteID];
      //g_print ("%s (type:%d; site:%d)\n", __func__, pItem->iFileType, pItem->iSiteID);
      gchar *cURL = pItem->cDistantUrls[pBackend->iPreferedUrlType];
      if (cURL == NULL)
      {
            int i;
            for (i = 0; i < pBackend->iNbUrls && cURL == NULL; i ++)
            {
                  cURL = pItem->cDistantUrls[i];
            }
      }
      return cURL;
}

void cd_dnd2share_set_current_url_from_item (CDUploadedItem *pItem)
{
      gchar *cURL = cd_dnd2share_get_prefered_url_from_item (pItem);
      g_free (myData.cLastURL);
      myData.cLastURL = g_strdup (cURL);
      
      int i = 0;
      GList *it;
      for (it = myData.pUpoadedItems; it != NULL; it = it->next)
      {
            if (it->data == pItem)
                  break ;
            i ++;
      }
      myData.iCurrentItemNum = i;
}


void cd_dnd2share_remove_one_item (CDUploadedItem *pItem)
{
      g_return_if_fail (pItem != NULL);
      
      // On enleve le groupe correspondant dans le fichier de l'historique.
      gchar *cConfFilePath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, "history.conf");
      if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))  // pas encore d'historique.
            return;
      
      GKeyFile *pKeyFile = cairo_dock_open_key_file (cConfFilePath);
      if (pKeyFile == NULL)  // probleme de droit ?
      {
            cd_warning ("Couldn't remove this item from history.");
            return ;
      }
      
      g_key_file_remove_group (pKeyFile, pItem->cItemName, NULL);
      cairo_dock_write_keys_to_file (pKeyFile, cConfFilePath);
      g_key_file_free (pKeyFile);
      g_free (cConfFilePath);
      
      // On efface sa copie de sauvegarde.
      gchar *cPreviewPath = g_strdup_printf ("%s/%s", myData.cWorkingDirPath, pItem->cItemName);
      g_remove (cPreviewPath);
      g_free (cPreviewPath);
      
      // Si c'est l'item courant, on pointe vers le suivant.
      if (myData.pUpoadedItems && myData.pUpoadedItems->data == pItem)
      {
            g_free (myData.cLastURL);
            myData.cLastURL = NULL;
            myData.iCurrentItemNum = 0;
            if (myData.pUpoadedItems->next != NULL)
            {
                  CDUploadedItem *pNextItem = myData.pUpoadedItems->next->data;
                  gchar *cURL = cd_dnd2share_get_prefered_url_from_item (pNextItem);
                  myData.cLastURL = g_strdup (cURL);
            }
      }
      
      // On enleve l'item de la liste.
      myData.pUpoadedItems = g_list_remove (myData.pUpoadedItems, pItem);
      cd_dnd2share_free_uploaded_item (pItem);
}


void cd_dnd2share_register_new_backend (CDFileType iFileType, const gchar *cSiteName, int iNbUrls, const gchar **cUrlLabels, int iPreferedUrlType, CDUploadFunc pUploadFunc)
{
      int iNumSite = myData.iNbSitesForType[iFileType];
      CDSiteBackend *pNewBackend = &myData.backends[iFileType][iNumSite];
      myData.iNbSitesForType[iFileType] ++;
      
      pNewBackend->cSiteName = cSiteName;
      pNewBackend->iNbUrls = iNbUrls;
      pNewBackend->cUrlLabels = cUrlLabels;
      pNewBackend->iPreferedUrlType = iPreferedUrlType;
      pNewBackend->upload = pUploadFunc;
}

Generated by  Doxygen 1.6.0   Back to index