#include "uninstallWidget.h"
#include "msgDialog.h"
#include "uninstall.h"
#include "inputDialog.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include "globe.xpm"
#include "folder.xpm"
#include "user.xpm"
#include "theme.xpm"
#define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
GtkWidget *mainUninstallTree,*systemMenu,*userMenu;
struct stInstalledThemell *selectedInstalledTheme,*global,*local;
struct stInstalledThemell *selectedInstalledDir,*movingTheme;
char systemInstallPath[PATH_MAX];
char userInstallPath[PATH_MAX];
int globalSelected;
int userSelected;
static void menuMoveTheme(GtkWidget *,struct stInstalledThemell *);
static void menuCreateSubfolder(GtkWidget *,struct stInstalledThemell *);
static void removeSubfolder(GtkWidget *,struct stInstalledThemell *);
static void userCreateSubfolder();
static void systemCreateSubfolder();
enum {
TARGET_URI_LIST
};
static GtkTargetEntry dropTypes[]={
{"test/uri-list",0,TARGET_URI_LIST}
};
void updateSystemMenu(void);
void updateUserMenu(void);
/*************** GTK Widget functions on the installed list *****************/
static void installedSelectTreeItem(GtkWidget *item,struct stInstalledThemell *pCurrent)
{
selectedInstalledTheme=pCurrent;
}
static void installedDeselectTreeItem(GtkWidget *item,struct stInstalledThemell *pCurrent)
{
selectedInstalledTheme=NULL;
}
static void installedSelectDirectory(GtkWidget *item,struct stInstalledThemell *pCurrent)
{
selectedInstalledTheme=NULL;
selectedInstalledDir=pCurrent;
}
static void globalDirectorySelected()
{
globalSelected=1;
}
static void globalDirectoryDeselected()
{
globalSelected=0;
}
static void userDirectorySelected()
{
userSelected=1;
}
static void userDirectoryDeselected()
{
userSelected=0;
}
void useThemeButtonClicked(GtkWidget *button)
{
char command[2048];
if (selectedInstalledTheme!=NULL) {
snprintf(command,2048,"setstyle \"%s\"",
selectedInstalledTheme->filename);
system(command);
} else {
showMessageDialog("Error","There is no theme currently\nselected to use.");
}
}
void uninstallThemeButtonClicked(GtkWidget *button)
{
if (selectedInstalledTheme!=NULL) {
uninstallTheme(selectedInstalledTheme);
updateInstalledTree(systemInstallPath,userInstallPath);
} else {
showMessageDialog("Error","There is no theme currently\nselected to uninstall.");
}
}
GtkWidget *createPixLabel(GtkWidget *window,char *pixmapData[],char *labelText)
{
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *pixmapWidget;
GdkPixmap *pixmap;
GdkBitmap *mask;
GtkWidget *test;
hbox=gtk_hbox_new(FALSE,0);
if (pixmapData!=NULL) {
pixmap=gdk_pixmap_create_from_xpm_d(window->window,&mask,
NULL,pixmapData);
pixmapWidget=gtk_pixmap_new(pixmap,mask);
gtk_box_pack_start(GTK_BOX(hbox),pixmapWidget,FALSE,FALSE,0);
gtk_widget_show(pixmapWidget);
}
label=gtk_label_new(labelText);
gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE,0);
gtk_widget_show(label);
gtk_widget_show(hbox);
return hbox;
}
/********************* Right button click stuff **********************/
void uninstallPopup(GtkWidget *widget,struct stInstalledThemell *current)
{
GtkWidget *item;
item=current->widget;
uninstallTheme(current);
refreshInstalledTree();
}
void popupChangeTo(GtkWidget *widget,struct stInstalledThemell *current)
{
char command[2048];
if (current!=NULL) {
snprintf(command,2048,"setstyle \"%s\"",
current->filename);
system(command);
} else {
showMessageDialog("Error","There is no theme currently\nselected to use.");
}
}
void themeButtonPress(GtkWidget *widget,GdkEventButton *event,
struct stInstalledThemell *current)
{
GtkWidget *menu;
GtkWidget *menuItem;
if (current&&(event->button==3)) {
/* This is where we need to handle the popup menu */
menu=gtk_menu_new();
menuItem=gtk_menu_item_new_with_label("Change to...");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(popupChangeTo),current);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
menuItem=gtk_menu_item_new_with_label("Move to...");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(menuMoveTheme),current);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
menuItem=gtk_menu_item_new_with_label("Uninstall");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(uninstallPopup),current);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,event->button,
event->time);
}
}
void folderButtonPress(GtkWidget *widget,GdkEventButton *event,
struct stInstalledThemell *current)
{
GtkWidget *menu;
GtkWidget *menuItem;
if (current&&(event->button==3)) {
menu=gtk_menu_new();
menuItem=gtk_menu_item_new_with_label("Create subfolder...");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(menuCreateSubfolder),current);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
if (current->child==NULL) {
menuItem=gtk_menu_item_new_with_label("Remove folder");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(removeSubfolder),current);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
}
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,event->button,
event->time);
}
}
void userButtonPress(GtkWidget *widget,GdkEventButton *event)
{
GtkWidget *menu;
GtkWidget *menuItem;
if (event->button==3) {
menu=gtk_menu_new();
menuItem=gtk_menu_item_new_with_label("Create subfoler...");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(userCreateSubfolder),NULL);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,event->button,
event->time);
}
}
void systemButtonPress(GtkWidget *widget,GdkEventButton *event)
{
GtkWidget *menu;
GtkWidget *menuItem;
if (event->button==3) {
menu=gtk_menu_new();
menuItem=gtk_menu_item_new_with_label("Create subfoler...");
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(systemCreateSubfolder),NULL);
gtk_menu_append(GTK_MENU(menu),menuItem);
gtk_widget_show(menuItem);
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,event->button,
event->time);
}
}
/******************* Drag and drop stuff *******************/
void installedDragDataGet(GtkWidget *temp,GdkDragContext *context,
GtkSelectionData *selData,gint info,guint tinm,gpointer data)
{
if (data) printf("%s\n",((struct stInstalledThemell *)data)->name);
}
static void setDraggable(GtkWidget *dragit,char *pixmapData[],
struct stInstalledThemell *data)
{
GdkBitmap *mask;
GdkPixmap *pixmap;
GdkColormap *colormap;
pixmap=gdk_pixmap_create_from_xpm_d(dragit->window,&mask,
NULL,pixmapData);
colormap=dragit->style->colormap;
gtk_drag_dest_set(dragit,GTK_DEST_DEFAULT_ALL,
dropTypes,ELEMENTS(dropTypes),
GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
gtk_drag_source_set(dragit,GDK_BUTTON1_MASK,dropTypes,
ELEMENTS(dropTypes),
GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
gtk_drag_source_set_icon(dragit,colormap,pixmap,mask);
/* gtk_signal_connect(GTK_OBJECT(dragit),"event",
GTK_SIGNAL_FUNC(gotEvent),(gpointer)data);*/
}
/************************ Widget Creation *************************/
void fillInstalledWidgetTree(GtkWidget *tree,struct stInstalledThemell *first)
{
GtkWidget *item;
struct stInstalledThemell *current=first;
while (current!=NULL) {
item=gtk_tree_item_new();
gtk_tree_append(GTK_TREE(tree),item);
gtk_widget_show(item);
current->widget=item;
if (current->themeType==DIRECTORY) {
GtkWidget *subtree;
GtkWidget *pixLabel;
pixLabel=createPixLabel(item,folder_xpm,current->name);
gtk_container_add(GTK_CONTAINER(item),pixLabel);
gtk_signal_connect(GTK_OBJECT(item),"select",
GTK_SIGNAL_FUNC(installedSelectDirectory),
current);
gtk_signal_connect(GTK_OBJECT(item),"button-press-event",
GTK_SIGNAL_FUNC(folderButtonPress),current);
subtree=gtk_tree_new();
gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),subtree);
fillInstalledWidgetTree(subtree,current->child);
} else {
gtk_container_add(GTK_CONTAINER(item),createPixLabel(item,theme_xpm,current->name));
gtk_signal_connect(GTK_OBJECT(item),"select",
GTK_SIGNAL_FUNC(installedSelectTreeItem),
current);
gtk_signal_connect(GTK_OBJECT(item),"deselect",
GTK_SIGNAL_FUNC(installedDeselectTreeItem),
current);
gtk_signal_connect(GTK_OBJECT(item),"button-press-event",
GTK_SIGNAL_FUNC(themeButtonPress),current);
// setDraggable(item,theme_xpm,current);
}
current=current->next;
}
}
void refreshInstalledTree()
{
updateInstalledTree(systemInstallPath,userInstallPath);
}
void updateInstalledTree(char *systemPath,char *userPath)
{
GtkWidget *item,*subtree;
global=getInstalledList(systemPath,GLOBAL_INSTALL);
local=getInstalledList(userPath,LOCAL_INSTALL);
strncpy(systemInstallPath,systemPath,PATH_MAX);
strncpy(userInstallPath,userPath,PATH_MAX);
if (mainUninstallTree==NULL) {
printf("The main installed tree does not exist!\n");
return;
}
gtk_tree_remove_items(GTK_TREE(mainUninstallTree),(GTK_TREE(mainUninstallTree))->children);
if (global!=NULL) {
item=gtk_tree_item_new();
gtk_tree_append(GTK_TREE(mainUninstallTree),item);
gtk_widget_show(item);
gtk_container_add(GTK_CONTAINER(item),createPixLabel(item,globe_xpm,"System"));
gtk_signal_connect(GTK_OBJECT(item),"select",
GTK_SIGNAL_FUNC(globalDirectorySelected),NULL);
gtk_signal_connect(GTK_OBJECT(item),"deselect",
GTK_SIGNAL_FUNC(globalDirectoryDeselected),NULL);
gtk_signal_connect(GTK_OBJECT(item),"button_press_event",
GTK_SIGNAL_FUNC(systemButtonPress),NULL);
subtree=gtk_tree_new();
gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),subtree);
fillInstalledWidgetTree(subtree,global);
gtk_tree_item_expand(GTK_TREE_ITEM(item));
}
item=gtk_tree_item_new();
gtk_tree_append(GTK_TREE(mainUninstallTree),item);
gtk_widget_show(item);
gtk_container_add(GTK_CONTAINER(item),createPixLabel(item,user_xpm,"User"));
gtk_signal_connect(GTK_OBJECT(item),"select",
GTK_SIGNAL_FUNC(userDirectorySelected),NULL);
gtk_signal_connect(GTK_OBJECT(item),"deselect",
GTK_SIGNAL_FUNC(userDirectoryDeselected),NULL);
gtk_signal_connect(GTK_OBJECT(item),"button_press_event",
GTK_SIGNAL_FUNC(userButtonPress),NULL);
subtree=gtk_tree_new();
gtk_tree_item_set_subtree(GTK_TREE_ITEM(item),subtree);
fillInstalledWidgetTree(subtree,local);
gtk_tree_item_expand(GTK_TREE_ITEM(item));
selectedInstalledTheme=NULL;
updateSystemMenu();
updateUserMenu();
}
GtkWidget *createInstalledWidget()
{
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *scrolledWindow,*tree;
GtkWidget *useThemeButton;
GtkWidget *uninstallThemeButton;
vbox=gtk_vbox_new(FALSE,0);
gtk_widget_show(vbox);
label=gtk_label_new("Installed WindowMaker Themes");
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0);
gtk_widget_show(label);
useThemeButton=gtk_button_new_with_label("Use Selected Theme");
gtk_box_pack_start(GTK_BOX(vbox),useThemeButton,FALSE,TRUE,0);
gtk_widget_show(useThemeButton);
gtk_signal_connect(GTK_OBJECT(useThemeButton),"clicked",
GTK_SIGNAL_FUNC(useThemeButtonClicked),NULL);
/* Create the scrolled widget */
scrolledWindow=gtk_scrolled_window_new(NULL,NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX(vbox),scrolledWindow,TRUE,TRUE,5);
gtk_widget_show(scrolledWindow);
/* Create the root tree */
tree=gtk_tree_new();
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledWindow),
tree);
gtk_tree_set_selection_mode(GTK_TREE(tree),GTK_SELECTION_SINGLE);
gtk_widget_show(tree);
mainUninstallTree=tree;
uninstallThemeButton=gtk_button_new_with_label("Uninstall Selected Theme");
gtk_box_pack_start(GTK_BOX(vbox),uninstallThemeButton,FALSE,TRUE,0);
gtk_widget_show(uninstallThemeButton);
gtk_signal_connect(GTK_OBJECT(uninstallThemeButton),"clicked",
GTK_SIGNAL_FUNC(uninstallThemeButtonClicked),NULL);
return vbox;
}
struct stInstalledThemell *getSelectedInstalledTheme(void)
{
return selectedInstalledTheme;
}
struct stInstalledThemell *checkForParent(struct stInstalledThemell *startTheme,
struct stInstalledThemell *checkTheme)
{
struct stInstalledThemell *current,*temp;
current=startTheme;
while (current!=NULL) {
if (current->child==checkTheme) {
return current;
}
if (current->child) {
temp=checkForParent(current->child,checkTheme);
if (temp) return (temp);
}
current=current->next;
}
return NULL;
}
void getInstalledDirectory(char *directory)
{
struct stInstalledThemell *current,*temp,*start,*first;
char tempDir[PATH_MAX];
memset(tempDir,0,PATH_MAX);
memset(directory,0,PATH_MAX);
current=selectedInstalledTheme;
if (current==NULL) {
current=selectedInstalledDir;
if (current)
snprintf(directory,PATH_MAX,"%s",current->name);
}
if (globalSelected) {
strncpy(directory,systemInstallPath,PATH_MAX);
return;
}
if (userSelected) {
strncpy(directory,userInstallPath,PATH_MAX);
return;
}
if (current==NULL) {
strcpy(directory,"");
return;
}
if (current->installType==GLOBAL_INSTALL) start=global;
if (current->installType==LOCAL_INSTALL) start=local;
first=current;
while (current!=NULL) {
if (current->prev==NULL) {
temp=checkForParent(start,current);
if (temp) {
snprintf(tempDir,PATH_MAX,"%s/%s",temp->name,directory);
strncpy(directory,tempDir,PATH_MAX);
current=temp;
}
}
if (current) current=current->prev;
}
if (first->installType==GLOBAL_INSTALL) {
snprintf(tempDir,PATH_MAX,"%s/%s",systemInstallPath,directory);
strncpy(directory,tempDir,PATH_MAX);
}
if (first->installType==LOCAL_INSTALL) {
snprintf(tempDir,PATH_MAX,"%s/%s",userInstallPath,directory);
strncpy(directory,tempDir,PATH_MAX);
}
}
/*************************** Theme moving functions ********************/
void moveOldTheme(char *newFilename)
{
FILE *fin,*fout;
char buffer[4096];
int numread;
fin=fopen(movingTheme->filename,"r");
if (fin==NULL) {
showMessageDialog("Error","Unable to open source theme");
return;
}
fout=fopen(newFilename,"w");
if (fout==NULL) {
showMessageDialog("Error","Unable to write to destination");
fclose(fin);
return;
}
numread=sizeof(buffer);
while (numread==sizeof(buffer)) {
numread=fread(buffer,1,sizeof(buffer),fin);
fwrite(buffer,1,numread,fout);
}
fclose(fin);
fclose(fout);
unlink(movingTheme->filename);
}
void moveNewTheme(char *newPath)
{
FILE *fin,*fout;
char buffer[4096];
int numread;
DIR *dir;
struct dirent *entry;
char newName[PATH_MAX];
char inFilename[PATH_MAX];
char outFilename[PATH_MAX];
int error;
snprintf(newName,PATH_MAX,"%s.themed/",newPath);
error=mkdir(newName,0777);
if (error) {
showMessageDialog("Error","Unable to create new directory");
return;
}
dir=opendir(movingTheme->filename);
if (dir==NULL) {
showMessageDialog("Error","Unable to open source directory");
unlink(newName);
return;
}
while ((entry=readdir(dir))!=NULL) {
if (strcmp(entry->d_name,".")&&strcmp(entry->d_name,"..")) {
snprintf(inFilename,PATH_MAX,"%s/%s",movingTheme->filename,
entry->d_name);
snprintf(outFilename,PATH_MAX,"%s%s",newName,entry->d_name);
fin=fopen(inFilename,"r");
fout=fopen(outFilename,"w");
numread=sizeof(buffer);
while (numread==sizeof(buffer)) {
numread=fread(buffer,1,sizeof(buffer),fin);
fwrite(buffer,1,numread,fout);
}
fclose(fin);
fclose(fout);
unlink(inFilename);
}
}
closedir(dir);
rmdir(movingTheme->filename);
}
/*************************** Menu Signal Functions *********************/
static void moveThemeReturned(char *newpath)
{
char newFilename[PATH_MAX];
snprintf(newFilename,PATH_MAX,"%s%s",newpath,movingTheme->name);
if (movingTheme->themeType==OLD_THEME) moveOldTheme(newFilename);
if (movingTheme->themeType==NEW_THEME) moveNewTheme(newFilename);
refreshInstalledTree();
}
static void menuMoveTheme(GtkWidget *widget,
struct stInstalledThemell *current)
{
char fullpath[PATH_MAX];
movingTheme=current;
if (current->installType==GLOBAL_INSTALL) {
snprintf(fullpath,PATH_MAX,"%s/anything",systemInstallPath);
} else {
snprintf(fullpath,PATH_MAX,"%s/anything",userInstallPath);
}
showThemeDirBrowser(GTK_SIGNAL_FUNC(moveThemeReturned),
fullpath);
}
static void removeSubfolder(GtkWidget *widget,
struct stInstalledThemell *current)
{
int error;
error=rmdir(current->filename);
if (error) {
showMessageDialog("Error","Unable to remove folder");
} else {
refreshInstalledTree();
}
}
static void createSubfolderReturn(char *path)
{
int error;
error=mkdir(path,0777);
if (error) {
showMessageDialog("Error","Unable to create folder");
} else {
refreshInstalledTree();
}
}
static void menuCreateSubfolder(GtkWidget *widget,
struct stInstalledThemell *current)
{
char fullPath[PATH_MAX];
snprintf(fullPath,PATH_MAX,"%s/",current->filename);
showInputDialog(GTK_SIGNAL_FUNC(createSubfolderReturn),
"New Folder Name","Name: ",fullPath);
}
static void systemCreateSubfolder()
{
char fullPath[PATH_MAX];
snprintf(fullPath,PATH_MAX,"%s/",systemInstallPath);
showInputDialog(GTK_SIGNAL_FUNC(createSubfolderReturn),
"New Folder Name","Name: ",fullPath);
}
static void userCreateSubfolder()
{
char fullPath[PATH_MAX];
snprintf(fullPath,PATH_MAX,"%s/",userInstallPath);
showInputDialog(GTK_SIGNAL_FUNC(createSubfolderReturn),
"New Folder Name","Name: ",fullPath);
}
/*************************** Menu update functions *********************/
void setSystemMenu(GtkWidget *menu)
{
systemMenu=menu;
}
void setUserMenu(GtkWidget *menu)
{
userMenu=menu;
}
void addThemeSubmenu(GtkWidget *menu,struct stInstalledThemell *first)
{
char menuName[256];
struct stInstalledThemell *current;
GtkWidget *submenu;
GtkWidget *menuItem;
current=first;
while (current!=NULL) {
if (current->themeType==DIRECTORY)
strncpy(menuName,current->name,256);
else
snprintf(menuName,256,"Move %s",current->name);
menuItem=gtk_menu_item_new_with_label(menuName);
gtk_widget_show(menuItem);
gtk_menu_append(GTK_MENU(menu),menuItem);
if (current->themeType==DIRECTORY) {
submenu=gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuItem),submenu);
if (current->child==NULL) {
menuItem=gtk_menu_item_new_with_label("Remove Folder");
gtk_widget_show(menuItem);
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(removeSubfolder),current);
gtk_menu_append(GTK_MENU(submenu),menuItem);
}
menuItem=gtk_menu_item_new_with_label("Create subfolder...");
gtk_widget_show(menuItem);
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(menuCreateSubfolder),current);
gtk_menu_append(GTK_MENU(submenu),menuItem);
if (current->child) {
addSeparator(submenu);
addThemeSubmenu(submenu,current->child);
}
} else {
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(menuMoveTheme),current);
}
current=current->next;
}
}
void updateSystemMenu()
{
GtkWidget *menu;
GtkWidget *menuItem;
gtk_widget_show(systemMenu);
menu=gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(systemMenu),menu);
menuItem=gtk_menu_item_new_with_label("Create subfolder...");
gtk_widget_show(menuItem);
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(systemCreateSubfolder),NULL);
gtk_menu_append(GTK_MENU(menu),menuItem);
addSeparator(menu);
addThemeSubmenu(menu,global);
}
void updateUserMenu()
{
GtkWidget *menu;
GtkWidget *menuItem;
gtk_widget_show(userMenu);
menu=gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(userMenu),menu);
menuItem=gtk_menu_item_new_with_label("Create subfolder...");
gtk_widget_show(menuItem);
gtk_signal_connect(GTK_OBJECT(menuItem),"activate",
GTK_SIGNAL_FUNC(userCreateSubfolder),NULL);
gtk_menu_append(GTK_MENU(menu),menuItem);
addSeparator(menu);
addThemeSubmenu(menu,local);
}
syntax highlighted by Code2HTML, v. 0.9.1