/* AbiWord * Copyright (C) 2001, 2002 Dom Lachowicz * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include <stdlib.h> #include <unistd.h> #include <dirent.h> #include "ut_string.h" #include "ut_assert.h" #include "ut_unixDirent.h" #include "ut_path.h" // This header defines some functions for Unix dialogs, // like centering them, measuring them, etc. #include "xap_UnixDialogHelper.h" #include "xap_App.h" #include "xap_UnixApp.h" #include "xap_UnixFrame.h" #include "ap_Strings.h" #include "ap_Dialog_Id.h" #include "ap_Dialog_New.h" #include "ap_UnixDialog_New.h" #include "xap_Dlg_FileOpenSaveAs.h" #include "ie_imp.h" #include "ut_string_class.h" /*************************************************************************/ XAP_Dialog * AP_UnixDialog_New::static_constructor(XAP_DialogFactory * pFactory, XAP_Dialog_Id id) { AP_UnixDialog_New * p = new AP_UnixDialog_New(pFactory,id); return p; } AP_UnixDialog_New::AP_UnixDialog_New(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id) : AP_Dialog_New(pDlgFactory,id), m_pFrame(0), mRow(0), mCol(0) { } AP_UnixDialog_New::~AP_UnixDialog_New(void) { UT_VECTOR_PURGEALL(UT_String*, mTemplates); } void AP_UnixDialog_New::runModal(XAP_Frame * pFrame) { UT_ASSERT(pFrame); m_pFrame = pFrame; // Build the window's widgets and arrange them GtkWidget * mainWindow = _constructWindow(); UT_ASSERT(mainWindow); connectFocus(GTK_WIDGET(mainWindow),pFrame); // To center the dialog, we need the frame of its parent. XAP_UnixFrame * pUnixFrame = static_cast<XAP_UnixFrame *>(pFrame); UT_ASSERT(pUnixFrame); // Get the GtkWindow of the parent frame GtkWidget * parentWindow = pUnixFrame->getTopLevelWindow(); UT_ASSERT(parentWindow); // Center our new dialog in its parent and make it a transient // so it won't get lost underneath centerDialog(parentWindow, mainWindow); // Show the top level dialog, gtk_widget_show(mainWindow); // Make it modal, and stick it up top gtk_grab_add(mainWindow); // Run into the GTK event loop for this window. gtk_main(); if(mainWindow && GTK_IS_WIDGET(mainWindow)) gtk_widget_destroy(mainWindow); } /*************************************************************************/ /*************************************************************************/ void AP_UnixDialog_New::event_Ok () { setAnswer (AP_Dialog_New::a_OK); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m_radioExisting))) { setOpenType(AP_Dialog_New::open_Existing); } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (m_radioNew))) { UT_String * tmpl = (UT_String*)mTemplates[mRow] ; if (tmpl && tmpl->c_str()) { setFileName (tmpl->c_str()); setOpenType(AP_Dialog_New::open_Template); } else { // fall back setOpenType(AP_Dialog_New::open_New); } } else { setOpenType(AP_Dialog_New::open_New); } gtk_main_quit(); } void AP_UnixDialog_New::event_Cancel () { setAnswer (AP_Dialog_New::a_CANCEL); gtk_main_quit(); } void AP_UnixDialog_New::event_ToggleOpenExisting () { XAP_Dialog_Id id = XAP_DIALOG_ID_FILE_OPEN; XAP_DialogFactory * pDialogFactory = (XAP_DialogFactory *) m_pFrame->getDialogFactory(); XAP_Dialog_FileOpenSaveAs * pDialog = (XAP_Dialog_FileOpenSaveAs *)(pDialogFactory->requestDialog(id)); UT_ASSERT(pDialog); pDialog->setCurrentPathname(0); pDialog->setSuggestFilename(false); UT_uint32 filterCount = IE_Imp::getImporterCount(); const char ** szDescList = (const char **) UT_calloc(filterCount + 1, sizeof(char *)); const char ** szSuffixList = (const char **) UT_calloc(filterCount + 1, sizeof(char *)); IEFileType * nTypeList = (IEFileType *) UT_calloc(filterCount + 1, sizeof(IEFileType)); UT_uint32 k = 0; while (IE_Imp::enumerateDlgLabels(k, &szDescList[k], &szSuffixList[k], &nTypeList[k])) k++; pDialog->setFileTypeList(szDescList, szSuffixList, (const UT_sint32 *) nTypeList); pDialog->setDefaultFileType(IE_Imp::fileTypeForSuffix(".abw")); pDialog->runModal(m_pFrame); XAP_Dialog_FileOpenSaveAs::tAnswer ans = pDialog->getAnswer(); bool bOK = (ans == XAP_Dialog_FileOpenSaveAs::a_OK); if (bOK) { const char * szResultPathname = pDialog->getPathname(); if (szResultPathname && *szResultPathname) { // update the entry box gtk_entry_set_text (GTK_ENTRY(m_entryFilename), szResultPathname); setFileName (szResultPathname); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(m_radioExisting), TRUE); } FREEP(szDescList); FREEP(szSuffixList); FREEP(nTypeList); pDialogFactory->releaseDialog(pDialog); } /*************************************************************************/ /*************************************************************************/ static void s_ok_clicked (GtkWidget *, AP_UnixDialog_New * dlg) { UT_ASSERT(dlg); dlg->event_Ok(); } static void s_cancel_clicked (GtkWidget *, AP_UnixDialog_New * dlg) { UT_ASSERT(dlg); dlg->event_Cancel(); } static void s_window_delete (GtkWidget *, gpointer, AP_UnixDialog_New * dlg) { s_cancel_clicked (0, dlg); } static void s_choose_clicked (GtkWidget * w, AP_UnixDialog_New * dlg) { dlg->event_ToggleOpenExisting(); } static void s_clist_clicked (GtkWidget *w, gint row, gint col, GdkEvent *evt, gpointer d) { AP_UnixDialog_New * dlg = static_cast <AP_UnixDialog_New *>(d); dlg->event_ClistClicked (row, col); } /*************************************************************************/ /*************************************************************************/ // return > 0 for directory entries ending in ".awt" and ".dot" #if defined (__APPLE__) || defined (__FreeBSD__) || defined (__OpenBSD__) \ || defined(_AIX) static int awt_only (struct dirent *d) #elif defined(__osf__) // The Tru64 UNIX vendor C++ compiler will complain when scandir is // called in _constructWindowContents because it expects the third argument to // scandir to be a pointer to a function with C linkage. Since that's // the case, make the function extern "C". extern "C" { static int awt_only (struct dirent *d) #else static int awt_only (const struct dirent *d) #endif { const char * name = d->d_name; if ( name ) { int len = strlen (name); if (len >= 4) { if(!strcmp(name+(len-4), ".awt") || !strcmp(name+(len-4), ".dot") ) return 1; } } return 0; } #if defined(__osf__) } // extern "C" #endif /*************************************************************************/ /*************************************************************************/ GtkWidget * AP_UnixDialog_New::_constructWindow () { GtkWidget *mainWindow; GtkWidget *dialog_vbox1; GtkWidget *hbuttonbox1; GtkWidget *dialog_action_area1; GtkWidget *ok_btn; GtkWidget *cancel_btn; const XAP_StringSet * pSS = m_pApp->getStringSet(); mainWindow = gtk_dialog_new (); gtk_window_set_title (GTK_WINDOW (mainWindow), pSS->getValue(AP_STRING_ID_DLG_NEW_Title)); gtk_window_set_policy (GTK_WINDOW (mainWindow), TRUE, TRUE, FALSE); dialog_vbox1 = GTK_DIALOG (mainWindow)->vbox; gtk_widget_show (dialog_vbox1); dialog_action_area1 = GTK_DIALOG (mainWindow)->action_area; gtk_widget_show (dialog_action_area1); gtk_container_set_border_width (GTK_CONTAINER (dialog_action_area1), 10); hbuttonbox1 = gtk_hbutton_box_new (); gtk_widget_show (hbuttonbox1); gtk_box_pack_start (GTK_BOX (dialog_action_area1), hbuttonbox1, TRUE, TRUE, 0); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_END); gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox1), 0); ok_btn = gtk_button_new_with_label (pSS->getValue(XAP_STRING_ID_DLG_OK)); gtk_widget_show (ok_btn); gtk_container_add (GTK_CONTAINER (hbuttonbox1), ok_btn); GTK_WIDGET_SET_FLAGS (ok_btn, GTK_CAN_DEFAULT); cancel_btn = gtk_button_new_with_label (pSS->getValue(XAP_STRING_ID_DLG_Cancel)); gtk_widget_show (cancel_btn); gtk_container_add (GTK_CONTAINER (hbuttonbox1), cancel_btn); GTK_WIDGET_SET_FLAGS (cancel_btn, GTK_CAN_DEFAULT); // assign pointers to widgets m_mainWindow = mainWindow; m_buttonOk = ok_btn; m_buttonCancel = cancel_btn; // construct the window contents _constructWindowContents (dialog_vbox1); _connectSignals (); return mainWindow; } void AP_UnixDialog_New::_constructWindowContents (GtkWidget * container) { GtkWidget *vbox1; GtkWidget *hbox1; GtkWidget *radio_new; GtkWidget *radio_existing; GtkWidget *radio_empty; GSList *vbox1_group = NULL; GtkWidget *choicesList; GtkWidget *hseparator1; GtkWidget *hseparator2; GtkWidget *hseparator3; GtkWidget *entry_filename; GtkWidget *choose_btn; GtkWidget *scrolledwindow1; GtkWidget *viewport1; const XAP_StringSet * pSS = m_pApp->getStringSet(); vbox1 = gtk_vbox_new (FALSE, 10); gtk_widget_show (vbox1); gtk_box_pack_start (GTK_BOX (container), vbox1, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER (vbox1), 6); hseparator1 = gtk_hseparator_new (); gtk_widget_show (hseparator1); gtk_box_pack_start (GTK_BOX (vbox1), hseparator1, TRUE, TRUE, 0); radio_new = gtk_radio_button_new_with_label (vbox1_group, pSS->getValue(AP_STRING_ID_DLG_NEW_Create)); vbox1_group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_new)); gtk_widget_show (radio_new); gtk_box_pack_start (GTK_BOX (vbox1), radio_new, FALSE, FALSE, 0); scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (scrolledwindow1); gtk_box_pack_start (GTK_BOX (vbox1), scrolledwindow1, TRUE, TRUE, 0); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); viewport1 = gtk_viewport_new (NULL, NULL); gtk_widget_show (viewport1); gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); choicesList = gtk_clist_new ( 1 ); gtk_clist_column_titles_passive (GTK_CLIST(choicesList)); gtk_widget_show (choicesList); gtk_container_add (GTK_CONTAINER (viewport1), choicesList); // TODO: find better size gtk_widget_set_usize ( choicesList, 150, 150 ) ; UT_String templateList[2]; UT_String templateDir; // the locally installed templates (per-user basis) templateDir = XAP_App::getApp()->getUserPrivateDirectory(); templateDir += "/templates/"; templateList[0] = templateDir; // the globally installed templates templateDir = XAP_App::getApp()->getAbiSuiteLibDir(); templateDir += "/templates/"; templateList[1] = templateDir; gtk_clist_freeze (GTK_CLIST (choicesList)); gtk_clist_clear (GTK_CLIST (choicesList)); unsigned int howManyAdded = 0 ; for ( unsigned int i = 0; i < (sizeof(templateList)/sizeof(templateList[0])); i++ ) { struct dirent **namelist = NULL; UT_sint32 n = 0; templateDir = templateList[i]; n = scandir(templateDir.c_str(), &namelist, awt_only, alphasort); if (n > 0) { while(n-- > 0) { UT_String myTemplate (templateDir + namelist[n]->d_name); UT_String * myTemplateCopy = new UT_String ( myTemplate ) ; mTemplates.addItem ( myTemplateCopy ) ; myTemplate = myTemplate.substr ( 0, myTemplate.size() - 4 ) ; gchar * txt[2]; txt[0] = (gchar*) UT_basename ( myTemplate.c_str() ); txt[1] = NULL; gtk_clist_append ( GTK_CLIST(choicesList), txt ) ; free (namelist[n]); howManyAdded++ ; } } } gtk_clist_thaw (GTK_CLIST (choicesList)); gtk_clist_select_row (GTK_CLIST (choicesList), 0, 0); // connect the select_row signal to the clist gtk_signal_connect (GTK_OBJECT (choicesList), "select_row", GTK_SIGNAL_FUNC (s_clist_clicked), (gpointer)this); // TODO? Put clist inside of scrolled window hseparator2 = gtk_hseparator_new (); gtk_widget_show (hseparator2); gtk_box_pack_start (GTK_BOX (vbox1), hseparator2, TRUE, TRUE, 0); radio_existing = gtk_radio_button_new_with_label (vbox1_group, pSS->getValue(AP_STRING_ID_DLG_NEW_Open)); vbox1_group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_existing)); gtk_widget_show (radio_existing); gtk_box_pack_start (GTK_BOX (vbox1), radio_existing, FALSE, FALSE, 0); hbox1 = gtk_hbox_new (FALSE, 0); gtk_widget_show (hbox1); gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0); entry_filename = gtk_entry_new (); gtk_widget_show (entry_filename); gtk_box_pack_start (GTK_BOX (hbox1), entry_filename, TRUE, TRUE, 0); gtk_entry_set_editable (GTK_ENTRY (entry_filename), FALSE); gtk_entry_set_text (GTK_ENTRY (entry_filename), pSS->getValue(AP_STRING_ID_DLG_NEW_NoFile)); choose_btn = gtk_button_new_with_label (pSS->getValue(AP_STRING_ID_DLG_NEW_Choose)); gtk_widget_show (choose_btn); gtk_box_pack_start (GTK_BOX (hbox1), choose_btn, FALSE, FALSE, 0); hseparator3 = gtk_hseparator_new (); gtk_widget_show (hseparator3); gtk_box_pack_start (GTK_BOX (vbox1), hseparator3, TRUE, TRUE, 0); radio_empty = gtk_radio_button_new_with_label (vbox1_group, pSS->getValue(AP_STRING_ID_DLG_NEW_StartEmpty)); vbox1_group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_empty)); gtk_widget_show (radio_empty); gtk_box_pack_start (GTK_BOX (vbox1), radio_empty, FALSE, FALSE, 0); // make this one the default gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_empty), TRUE); // connect signals gtk_signal_connect (GTK_OBJECT(choose_btn), "clicked", GTK_SIGNAL_FUNC(s_choose_clicked), (gpointer)this); // set the private pointers m_radioNew = radio_new; m_radioExisting = radio_existing; m_radioEmpty = radio_empty; m_entryFilename = entry_filename; m_choicesList = choicesList; } void AP_UnixDialog_New::_connectSignals () { // the control buttons gtk_signal_connect(GTK_OBJECT(m_buttonOk), "clicked", GTK_SIGNAL_FUNC(s_ok_clicked), (gpointer) this); gtk_signal_connect(GTK_OBJECT(m_buttonCancel), "clicked", GTK_SIGNAL_FUNC(s_cancel_clicked), (gpointer) this); // the catch-alls gtk_signal_connect(GTK_OBJECT(m_mainWindow), "delete_event", GTK_SIGNAL_FUNC(s_window_delete), (gpointer) this); gtk_signal_connect_after(GTK_OBJECT(m_mainWindow), "destroy", NULL, NULL); }