glom r1487 - in trunk: . glom
- From: arminb svn gnome org
- To: svn-commits-list gnome org
- Subject: glom r1487 - in trunk: . glom
- Date: Sun, 30 Mar 2008 15:16:30 +0100 (BST)
Author: arminb
Date: Sun Mar 30 15:16:29 2008
New Revision: 1487
URL: http://svn.gnome.org/viewvc/glom?rev=1487&view=rev
Log:
2008-03-30 Armin Burgmeier <armin openismus com>
* glom/glom.glade:
* glom/dialog_existing_or_new.h:
* glom/dialog_existing_or_new.cc:
* glom/Makefile.am: Redesigned initial dialog, as described in
http://www.murrayc.com/blog/permalink/2007/11/29/gloms-initial-dialog.
* glom/application.h:
* glom/application.cc: Actually use it.
Added:
trunk/glom/dialog_existing_or_new.cc
trunk/glom/dialog_existing_or_new.h
Modified:
trunk/ChangeLog
trunk/glom/Makefile.am
trunk/glom/application.cc
trunk/glom/application.h
trunk/glom/glom.glade
Modified: trunk/glom/Makefile.am
==============================================================================
--- trunk/glom/Makefile.am (original)
+++ trunk/glom/Makefile.am Sun Mar 30 15:16:29 2008
@@ -39,6 +39,7 @@
combobox_fields.h combobox_fields.cc \
combobox_relationship.h combobox_relationship.cc \
dialog_connection.h dialog_connection.cc \
+ dialog_existing_or_new.h dialog_existing_or_new.cc \
dialog_invalid_data.h dialog_invalid_data.cc \
filechooser_export.h filechooser_export.cc \
box_reports.h box_reports.cc \
Modified: trunk/glom/application.cc
==============================================================================
--- trunk/glom/application.cc (original)
+++ trunk/glom/application.cc Sun Mar 30 15:16:29 2008
@@ -19,6 +19,7 @@
*/
#include "application.h"
+#include "dialog_existing_or_new.h"
#include <glom/libglom/dialog_progress_creating.h>
@@ -1161,116 +1162,52 @@
return false;
#endif
- Gtk::Dialog* dialog = 0;
- refXml->get_widget("dialog_existing_or_new", dialog);
+ Dialog_ExistingOrNew* dialog_raw = 0;
+ refXml->get_widget_derived("dialog_existing_or_new", dialog_raw);
+ std::auto_ptr<Dialog_ExistingOrNew> dialog(dialog_raw);
dialog->set_transient_for(*this);
- Gtk::RecentChooserWidget* recent_chooser = NULL;
- refXml->get_widget("existing_or_new_recentchooser", recent_chooser);
+ dialog->signal_new().connect(sigc::mem_fun(*this, &App_Glom::on_existing_or_new_new));
+ dialog->signal_open_from_uri().connect(sigc::mem_fun(*this, &App_Glom::on_existing_or_new_open_from_uri));
+ dialog->signal_open_from_remote().connect(sigc::mem_fun(*this, &App_Glom::on_existing_or_new_open_from_remote));
- Gtk::RecentFilter filter;
- filter.add_mime_type("application/x-glom");
- recent_chooser->set_filter(filter);
-
- /* Don't show files that don't exist anymore: */
- recent_chooser->set_show_not_found(FALSE);
-
- Gtk::Frame* recent_frame = NULL;
- refXml->get_widget("existing_or_new_recentchooser_frame", recent_frame);
-
- // Hide the recent chooser when they are not any recently used files
- if(recent_chooser->get_items().empty()) recent_frame->hide();
- recent_chooser->signal_item_activated().connect(sigc::bind(sigc::mem_fun(*dialog, &Gtk::Dialog::response), 1)); // Open
-
-#ifdef GLOM_ENABLE_CLIENT_ONLY
- // Don't offer the user the chance to create a new document, because without
- // developer mode he couldn't do anything useful with it, anyway.
- Gtk::Button* new_button;
- refXml->get_widget("existing_or_new_button_new", new_button);
- new_button->hide();
-
- refXml->get_widget("existing_or_new_button_example", new_button);
- new_button->hide();
-
- // Show another label that does not ask whether one wants to create a new
- // document because that is not possible in client only mode
- // TODO: Add another text, or simply hide the label?
- Gtk::Label* label = 0;
- refXml->get_widget("existing_or_new_label", label);
- label->set_markup(_("<span weight='bold' size='larger'>Open existing document</span>\n"));
-#endif // GLOM_ENABLE_CLIENT_ONLY
-
-#ifdef GLOM_ENABLE_MAEMO
- // Set dialog title to not show <unnamed> (default on maemo for empty title)
- // Strip terminating newline.
- dialog->set_title(label->get_text().substr(0, label->get_text().length()-1)); //TODO: Make this more robust.
- label->hide();
-
- // Stop the dialog from being too wide:
- recent_chooser->set_size_request(500, -1);
-#endif
-
- const int response_id = dialog->run();
- Glib::ustring selected_uri = recent_chooser->get_current_uri();
-
- delete dialog;
- dialog = 0;
-
- if(response_id == 1) //Open
+ bool ask_again = true;
+ while(ask_again)
{
- // When a recent document was selected, open that one instead.
- if(selected_uri.empty())
- on_menu_file_open();
- else
- open_document(selected_uri);
+ const int response_id = dialog->run();
+ dialog->hide();
- //Check that a document was opened:
- Document_Glom* document = dynamic_cast<Document_Glom*>(get_document());
- if(document->get_file_uri().empty() && !(document->get_opened_from_browse()))
+ if(response_id == Gtk::RESPONSE_ACCEPT)
{
- //Ask again:
- return offer_new_or_existing();
+ //Check that a document was opened:
+ Document_Glom* document = dynamic_cast<Document_Glom*>(get_document());
+ if(!document->get_file_uri().empty() || (document->get_opened_from_browse()))
+ ask_again = false;
}
- }
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- else if(response_id == 3) //Open Example
- {
- //Based on on_menu_file_open();
-
- //Display File Open dialog and respond to choice:
-
- //Bring document window to front, to make it clear which document is being changed:
- ui_bring_to_front();
-
- //Ask user to choose file to open:
- //Create a URI (prefixed by file://) for this path).
- //Previous versions of gnome-vfs could handle this without file://,
- //but that stopped working at some point around Ubuntu Hardy. murrayc.
- //g_warning("GLOM_EXAMPLES_DIR=%s", GLOM_EXAMPLES_DIR);
- Glib::ustring examples_uri;
- try
+ else if((response_id == Gtk::RESPONSE_CANCEL) || (response_id == Gtk::RESPONSE_DELETE_EVENT))
{
- examples_uri = Glib::filename_to_uri(GLOM_EXAMPLES_DIR);
+ return false; //close the window to close the application, because they need to choose a new or existing document.
}
- catch(const Glib::Error& ex)
+ else
{
- std::cerr << "Glom: Error converting examples path to a URI: " << ex.what() << std::endl;
+ //Do nothing. TODO: Do something?
}
-
- Glib::ustring file_uri = ui_file_select_open(examples_uri);
- if(!file_uri.empty())
- open_document(file_uri);
+ }
- //Check that a document was opened:
- Document_Glom* document = dynamic_cast<Document_Glom*>(get_document());
- if(document->get_file_uri().empty())
- {
- //Ask again:
- return offer_new_or_existing();
- }
+ return true;
+}
+
+void App_Glom::on_existing_or_new_new(const std::string& template_uri)
+{
+ if(!template_uri.empty())
+ {
+ // New from template
+ open_document(template_uri);
}
- else if(response_id == 2) //New
+ else
{
+ // New empty document
+
//Each document must have a location, so ask the user for one.
//This will use an extended save dialog that also asks for the database title and some hosting details:
Glib::ustring db_title;
@@ -1297,93 +1234,70 @@
document->set_connection_try_other_ports(!m_ui_save_extra_newdb_selfhosted);
//Each new document must have an associated new database,
- //so ask the user for the name of one to create:
-
+ //so choose a name
- bool keep_asking = true;
- while(keep_asking)
+ //Create a database name based on the title.
+ //The user will (almost) never see this anyway but it's nicer than using a random number:
+ Glib::ustring db_name = Utils::create_name_from_title(db_title);
+
+ //Prefix glom_ to the database name, so it's more obvious
+ //for the system administrator.
+ //This database name should never be user-visible again, either prefixed or not prefixed.
+ db_name = "glom_" + db_name;
+
+ //Connect to the server and choose a variation of this db_name that does not exist yet:
+ document->set_connection_database(db_name);
+ document->set_connection_is_self_hosted(self_hosted);
+
+#ifndef GLOM_ENABLE_CLIENT_ONLY
+ //Tell the connection pool about the document:
+ ConnectionPool* connection_pool = ConnectionPool::get_instance();
+ if(connection_pool)
+ connection_pool->set_get_document_func( sigc::mem_fun(*this, &App_Glom::on_connection_pool_get_document) );
+#endif
+
+ const bool connected = m_pFrame->connection_request_password_and_choose_new_database_name();
+ if(!connected)
+ {
+ // Unset URI so that the offer_new_or_existing does not disappear
+ // so the user can make a different choice about what document to open.
+ // TODO: Show some error message?
+ document->set_file_uri("");
+ }
+ else
{
- //Create a database name based on the title.
- //The user will (almost) never see this anyway but it's nicer than using a random number:
- Glib::ustring db_name = Utils::create_name_from_title(db_title);
-
- //Prefix glom_ to the database name, so it's more obvious
- //for the system administrator.
- //This database name should never be user-visible again, either prefixed or not prefixed.
- db_name = "glom_" + db_name;
-
- if(!db_name.empty()) //The dialog and prefix prevent this anyway.
+ const bool db_created = m_pFrame->create_database(document->get_connection_database(), db_title, false /* do not request password */);
+ if(db_created)
{
- //Connect to the server and choose a variation of this db_name that does not exist yet:
- document->set_connection_database(db_name);
- document->set_connection_is_self_hosted(self_hosted);
-
-#ifndef GLOM_ENABLE_CLIENT_ONLY
- //Tell the connection pool about the document:
- ConnectionPool* connection_pool = ConnectionPool::get_instance();
- if(connection_pool)
- connection_pool->set_get_document_func( sigc::mem_fun(*this, &App_Glom::on_connection_pool_get_document) );
-#endif
-
- const bool connected = m_pFrame->connection_request_password_and_choose_new_database_name();
- if(!connected)
- return false;
-
- const bool db_created = m_pFrame->create_database(document->get_connection_database(), db_title, false /* do not request password */);
- if(db_created)
- {
- keep_asking = false;
-
- //document->set_connection_database(db_name); //Select the database that was just created.
-
- /*
- ConnectionPool* connection_pool = ConnectionPool::get_instance();
- if(connection_pool)
- {
- connection_pool->set_database(db_name); //The rest has been set while creating the database.
- }
- */
-
- const Glib::ustring database_name_used = document->get_connection_database();
- ConnectionPool::get_instance()->set_database(database_name_used);
- document->set_database_title(db_title);
- m_pFrame->set_databases_selected(database_name_used);
- }
- else
- {
- //Ask again:
- return offer_new_or_existing();
- }
+ const Glib::ustring database_name_used = document->get_connection_database();
+ ConnectionPool::get_instance()->set_database(database_name_used);
+ document->set_database_title(db_title);
+ m_pFrame->set_databases_selected(database_name_used);
}
else
{
- g_warning(" App_Glom::offer_new_or_existing(): db_name is empty.");
- //And ask again, by going back to the start of the while() loop.
+ // Unset URI so that the offer_new_or_existing does not disappear
+ // so the user can make a different choice about what document to open.
+ // TODO: Show some error message?
+ document->set_file_uri("");
}
-
- } /* while() */
-
- return true; //File successfully created.
-
- }
- else
- {
- //Ask again:
- return offer_new_or_existing();
+ }
}
}
-#endif // !GLOM_ENABLE_CLIENT_ONLY
- else if((response_id == Gtk::RESPONSE_CANCEL) || (response_id == Gtk::RESPONSE_DELETE_EVENT))
- {
- return false; //close the window to close the application, because they need to choose a new or existing document.
- }
- else
- {
- //Do nothing. TODO: Do something?
- }
+}
- return true;
+void App_Glom::on_existing_or_new_open_from_uri(const std::string& document_uri)
+{
+ open_document(document_uri);
+}
+
+#ifndef G_OS_WIN32
+void App_Glom::on_existing_or_new_open_from_remote(EpcServiceInfo* info, const Glib::ustring& service_name)
+{
+ open_browsed_document(info, service_name);
}
+#endif
+
void App_Glom::set_mode_data()
{
m_action_mode_data->activate();
Modified: trunk/glom/application.h
==============================================================================
--- trunk/glom/application.h (original)
+++ trunk/glom/application.h Sun Mar 30 15:16:29 2008
@@ -98,6 +98,13 @@
bool offer_new_or_existing();
+ void on_existing_or_new_new(const std::string& template_uri);
+ void on_existing_or_new_open_from_uri(const std::string& document_uri);
+
+#ifndef G_OS_WIN32
+ void on_existing_or_new_open_from_remote(EpcServiceInfo* info, const Glib::ustring& service_name);
+#endif
+
void on_menu_help_contents();
#ifndef GLOM_ENABLE_CLIENT_ONLY
void on_menu_userlevel_developer();
Added: trunk/glom/dialog_existing_or_new.cc
==============================================================================
--- (empty file)
+++ trunk/glom/dialog_existing_or_new.cc Sun Mar 30 15:16:29 2008
@@ -0,0 +1,498 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * 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 "config.h"
+#include "dialog_existing_or_new.h"
+
+#include <libxml++/parsers/saxparser.h>
+
+#include <glibmm/i18n.h>
+#include <giomm/contenttype.h>
+#include <gtkmm/recentmanager.h>
+#include <gtkmm/filechooserdialog.h>
+#include <gtkmm/stock.h>
+
+#ifdef G_OS_WIN32
+# include <glib/gwin32.h>
+#else
+# include <libepc/service-type.h>
+#endif
+
+#include <iostream>
+
+namespace
+{
+
+// Reads the title of an example from the first few characters of the XML
+class Parser: public xmlpp::SaxParser
+{
+public:
+ Parser() {}
+
+ Glib::ustring get_example_title(const std::string& beginning)
+ {
+ parse_chunk(beginning);
+ return m_title;
+ }
+
+protected:
+ virtual void on_start_element(const Glib::ustring& name, const AttributeList& attributes)
+ {
+ if(m_title.empty()) // Already found name? Wait for parse_chunk() call to return.
+ {
+ if(name == "glom_document")
+ {
+ for(AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++ iter)
+ {
+ if(iter->name == "database_title")
+ {
+ m_title = iter->value;
+ // TODO: We should stop parsing here somehow, but I don't
+ // think we can throw an exception through the C library back
+ // to get_example_name, and there does not seem to be API to
+ // stop parsing.
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ Glib::ustring m_title;
+};
+
+}
+
+namespace Glom
+{
+
+Dialog_ExistingOrNew::Dialog_ExistingOrNew(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade)
+: Gtk::Dialog(cobject)
+{
+ refGlade->get_widget("existing_or_new_existing_treeview", m_existing_view);
+ refGlade->get_widget("existing_or_new_new_treeview", m_new_view);
+
+ if(!m_existing_view || !m_new_view)
+ throw std::runtime_error("Glade file does not contain treeviews for ExistingOrNew dialog");
+
+ m_existing_model = Gtk::TreeStore::create(m_existing_columns);
+ m_existing_model->set_sort_column(m_existing_columns.m_col_time, Gtk::SORT_DESCENDING);
+ m_existing_view->set_model(m_existing_model);
+
+ m_new_model = Gtk::TreeStore::create(m_new_columns);
+ m_new_view->set_model(m_new_model);
+
+ m_existing_column_title.set_expand(true);
+ m_existing_column_title.pack_start(m_existing_icon_renderer, false);
+ m_existing_column_title.pack_start(m_existing_title_renderer, true);
+ m_existing_column_title.set_cell_data_func(m_existing_icon_renderer, sigc::mem_fun(*this, &Dialog_ExistingOrNew::existing_icon_data_func));
+ m_existing_column_title.add_attribute(m_existing_title_renderer, "text", m_existing_columns.m_col_title.index());
+ m_existing_view->append_column(m_existing_column_title);
+
+ m_existing_column_button.pack_end(m_existing_button_renderer, false);
+ m_existing_column_button.add_attribute(m_existing_button_renderer, "text", m_existing_columns.m_col_button_text.index());
+ m_existing_view->append_column(m_existing_column_button);
+
+ m_new_column_title.set_expand(true);
+ m_new_column_title.pack_start(m_new_icon_renderer, false);
+ m_new_column_title.pack_start(m_new_title_renderer, true);
+ m_new_column_title.set_cell_data_func(m_new_icon_renderer, sigc::mem_fun(*this, &Dialog_ExistingOrNew::new_icon_data_func));
+ m_new_column_title.add_attribute(m_new_title_renderer, "text", m_new_columns.m_col_title.index());
+ m_new_view->append_column(m_new_column_title);
+
+ m_new_column_button.pack_end(m_new_button_renderer, false);
+ m_new_column_button.add_attribute(m_new_button_renderer, "text", m_new_columns.m_col_button_text.index());
+ m_new_view->append_column(m_new_column_button);
+
+ m_existing_view->set_headers_visible(false);
+ m_existing_view->signal_row_activated().connect(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_existing_row_activated));
+ m_existing_button_renderer.signal_clicked().connect(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_existing_button_clicked));
+ m_new_view->set_headers_visible(false);
+ m_new_view->signal_row_activated().connect(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_new_row_activated));
+ m_new_button_renderer.signal_clicked().connect(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_new_button_clicked));
+
+ m_iter_existing_recent = m_existing_model->append();
+ (*m_iter_existing_recent)[m_existing_columns.m_col_title] = _("Recently Opened");
+
+ m_iter_existing_network = m_existing_model->append();
+ (*m_iter_existing_network)[m_existing_columns.m_col_title] = _("Local Network");
+
+ m_iter_existing_other = m_existing_model->append();
+ (*m_iter_existing_other)[m_existing_columns.m_col_title] = _("Other");
+ (*m_iter_existing_other)[m_existing_columns.m_col_button_text] = _("Select Fileâ");
+
+ m_iter_new_empty = m_new_model->append();
+ (*m_iter_new_empty)[m_new_columns.m_col_title] = _("New Empty Document");
+ (*m_iter_new_empty)[m_new_columns.m_col_button_text] = _("Create");
+
+ m_iter_new_template = m_new_model->append();
+ (*m_iter_new_template)[m_new_columns.m_col_title] = _("New From Template");
+
+ // Load example files
+#ifdef G_OS_WIN32
+ gchar* dir = g_win32_get_package_installation_subdirectory(NULL, NULL, "share/doc/examples");
+ std::string path(dir);
+ g_free(dir);
+#else
+ const char* path = GLOM_EXAMPLES_DIR;
+#endif
+
+ m_examples_dir = Gio::File::create_for_path(path);
+
+ try
+ {
+ m_examples_dir->enumerate_children_async(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_enumerate_children),
+ G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE","G_FILE_ATTRIBUTE_STANDARD_NAME);
+ // TODO: Monitor example directory for new/removed files?
+ }
+ catch(const Glib::Exception& ex)
+ {
+ std::cerr << "Could not enumerate examples: " << ex.what() << std::endl;
+ }
+
+ // Browse local network
+#ifndef G_OS_WIN32
+ gchar* service_type = epc_service_type_new(EPC_PROTOCOL_HTTPS, "glom");
+ m_service_monitor = epc_service_monitor_new_for_types(NULL, service_type, NULL);
+ g_signal_connect(m_service_monitor, "service-found", G_CALLBACK(on_service_found_static), this);
+ g_signal_connect(m_service_monitor, "service-removed", G_CALLBACK(on_service_removed_static), this);
+ g_free(service_type);
+#endif
+
+ // Add recently used files
+ Gtk::RecentManager::ListHandle_RecentInfos infos = Gtk::RecentManager::get_default()->get_items();
+ for(Gtk::RecentManager::ListHandle_RecentInfos::const_iterator iter = infos.begin(); iter != infos.end(); ++ iter)
+ {
+ Glib::RefPtr<Gtk::RecentInfo> info = *iter;
+ if(info->get_mime_type() == "application/x-glom")
+ {
+ Gtk::TreeIter iter = m_existing_model->append(m_iter_existing_recent->children());
+ (*iter)[m_existing_columns.m_col_title] = info->get_display_name();
+ (*iter)[m_existing_columns.m_col_time] = info->get_modified();
+ (*iter)[m_existing_columns.m_col_button_text] = _("Open");
+ (*iter)[m_existing_columns.m_col_recent_info] = new Glib::RefPtr<Gtk::RecentInfo>(info);
+ }
+ }
+}
+
+Dialog_ExistingOrNew::~Dialog_ExistingOrNew()
+{
+ if(m_service_monitor)
+ {
+ g_object_unref(m_service_monitor);
+ m_service_monitor = NULL;
+ }
+
+#ifndef G_OS_WIN32
+ // Release the service infos in the treestore
+ {
+ const Gtk::TreeNodeChildren& children = m_iter_existing_network->children();
+ for(Gtk::TreeIter iter = children.begin(); iter != children.end(); ++ iter)
+ epc_service_info_unref((*iter)[m_existing_columns.m_col_service_info]);
+ }
+#endif
+
+ // Release the recent infos (see comment in the header for why these
+ // have to be dynamically allocated)
+ {
+ const Gtk::TreeNodeChildren& children = m_iter_existing_recent->children();
+ for(Gtk::TreeIter iter = children.begin(); iter != children.end(); ++ iter)
+ {
+ Glib::RefPtr<Gtk::RecentInfo>* info = (*iter)[m_existing_columns.m_col_recent_info];
+ delete info;
+ }
+ }
+}
+
+void Dialog_ExistingOrNew::existing_icon_data_func(Gtk::CellRenderer* renderer, const Gtk::TreeIter& iter)
+{
+ Gtk::CellRendererPixbuf* pixbuf_renderer = dynamic_cast<Gtk::CellRendererPixbuf*>(renderer);
+ if(!pixbuf_renderer) throw std::logic_error("Renderer not a pixbuf renderer in existing_icon_data_func");
+
+ pixbuf_renderer->property_stock_size() = Gtk::ICON_SIZE_BUTTON;
+ pixbuf_renderer->property_stock_id() = "";
+ pixbuf_renderer->property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>();
+
+ if(iter == m_iter_existing_recent)
+ pixbuf_renderer->property_stock_id() = Gtk::Stock::INDEX.id; // TODO: More meaningful icon?
+ else if(iter == m_iter_existing_network)
+ pixbuf_renderer->property_stock_id() = Gtk::Stock::NETWORK.id;
+ else if(iter == m_iter_existing_other)
+ pixbuf_renderer->property_stock_id() = Gtk::Stock::OPEN.id;
+ else
+ {
+ if(m_existing_model->is_ancestor(m_iter_existing_recent, iter))
+ {
+ //Glib::RefPtr<Gtk::RecentInfo>* info = (*iter)[m_existing_columns.m_col_recent_info];
+ //pixbuf_renderer->property_pixbuf() = (*info)->get_icon(Gtk::ICON_SIZE_BUTTON);
+ pixbuf_renderer->set_property("icon-name", Glib::ustring("glom"));
+ }
+ else if(m_existing_model->is_ancestor(m_iter_existing_network, iter))
+ {
+ //pixbuf_renderer->property_stock_id() = Gtk::Stock::CONNECT.id;
+ pixbuf_renderer->set_property("icon-name", Glib::ustring("glom"));
+ }
+ else
+ {
+ throw std::logic_error("Unexpected iterator in existing_icon_data_func");
+ }
+ }
+}
+
+void Dialog_ExistingOrNew::new_icon_data_func(Gtk::CellRenderer* renderer, const Gtk::TreeIter& iter)
+{
+ Gtk::CellRendererPixbuf* pixbuf_renderer = dynamic_cast<Gtk::CellRendererPixbuf*>(renderer);
+ if(!pixbuf_renderer) throw std::logic_error("Renderer not a pixbuf renderer in new_icon_data_func");
+
+ pixbuf_renderer->property_stock_size() = Gtk::ICON_SIZE_BUTTON;
+ pixbuf_renderer->property_stock_id() = "";
+ pixbuf_renderer->property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>();
+
+ if(iter == m_iter_new_empty)
+ pixbuf_renderer->property_stock_id() = Gtk::Stock::NEW.id;
+ else if(iter == m_iter_new_template)
+ pixbuf_renderer->property_stock_id() = Gtk::Stock::EDIT.id; // TODO: More meaningful icon?
+ else
+ {
+ if(m_new_model->is_ancestor(m_iter_new_template, iter))
+ {
+ pixbuf_renderer->set_property("icon-name", Glib::ustring("glom"));
+ }
+ else
+ {
+ throw std::logic_error("Unexpected iterator in new_icon_data_func");
+ }
+ }
+}
+
+void Dialog_ExistingOrNew::on_enumerate_children(const Glib::RefPtr<Gio::AsyncResult>& res)
+{
+ try
+ {
+ m_examples_enumerator = m_examples_dir->enumerate_children_finish(res);
+ m_examples_enumerator->next_files_async(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_next_files));
+ }
+ catch(const Glib::Exception& ex)
+ {
+ std::cerr << "Could not enumerate examples: " << ex.what() << std::endl;
+
+ m_examples_enumerator.reset();
+ m_examples_dir.reset();
+ }
+}
+
+void Dialog_ExistingOrNew::on_next_files(const Glib::RefPtr<Gio::AsyncResult>& res)
+{
+ try
+ {
+ const Glib::ListHandle<Glib::RefPtr<Gio::FileInfo> >& list = m_examples_enumerator->next_files_finish(res);
+ if (list.empty())
+ {
+ // Done
+ m_examples_dir.reset();
+ m_examples_enumerator.reset();
+ }
+ else
+ {
+ // Load file
+ Glib::RefPtr<Gio::FileInfo> info = *list.begin();
+ Glib::ustring content_type = info->get_attribute_string(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
+ Glib::ustring mime_type = Gio::content_type_get_mime_type(content_type);
+
+ if(mime_type == "application/x-glom")
+ {
+ m_current_example = Gio::File::create_for_path(Glib::build_filename(m_examples_dir->get_path(), info->get_name()));
+ m_current_example->read_async(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_read));
+ }
+ else
+ {
+ // File is not a glom file, continue with next
+ m_examples_enumerator->next_files_async(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_next_files));
+ }
+ }
+ }
+ catch(const Glib::Exception& ex)
+ {
+ std::cerr << "Could not enumerate examples: " << ex.what() << std::endl;
+
+ m_examples_dir.reset();
+ m_examples_enumerator.reset();
+ }
+}
+
+void Dialog_ExistingOrNew::on_read(const Glib::RefPtr<Gio::AsyncResult>& res)
+{
+ try
+ {
+ m_current_stream = m_current_example->read_finish(res);
+ m_current_buffer.reset(new buffer);
+ m_current_stream->read_async(m_current_buffer->buf, buffer::SIZE, sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_stream_read));
+ }
+ catch(const Glib::Exception& exception)
+ {
+ // Could not read this file, read next
+ m_examples_enumerator->next_files_async(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_next_files));
+
+ m_current_example.reset();
+ m_current_stream.reset();
+ m_current_buffer.reset();
+ }
+}
+
+void Dialog_ExistingOrNew::on_stream_read(const Glib::RefPtr<Gio::AsyncResult>& res)
+{
+ try
+ {
+ gssize size_read = m_current_stream->read_finish(res);
+ std::string data(m_current_buffer->buf, size_read);
+ // TODO: Check that data is valid UTF-8, the last character might be truncated
+
+ Parser parser;
+ Glib::ustring title = parser.get_example_title(data);
+
+ if(title.empty())
+ {
+ // TODO: Read more data from this file?
+ }
+ else
+ {
+ // Add to list
+ Gtk::TreeIter iter = m_new_model->append(m_iter_new_template->children());
+ (*iter)[m_new_columns.m_col_title] = title;
+ (*iter)[m_new_columns.m_col_button_text] = _("Create");
+ (*iter)[m_new_columns.m_col_template_uri] = m_current_example->get_uri();
+ }
+ }
+ catch(const Glib::Exception& ex)
+ {
+ std::cerr << "Could not read " << m_current_example->get_path() << ": " << ex.what() << std::endl;
+ }
+
+ // Done with this, read next file
+ m_current_example.reset();
+ m_current_stream.reset();
+ m_current_buffer.reset();
+
+ m_examples_enumerator->next_files_async(sigc::mem_fun(*this, &Dialog_ExistingOrNew::on_next_files));
+}
+
+#ifndef G_OS_WIN32
+void Dialog_ExistingOrNew::on_service_found(const Glib::ustring& name, EpcServiceInfo* info)
+{
+ gchar* title = g_strdup_printf(_("%s on %s (via %s)"), name.c_str(), epc_service_info_get_host(info), epc_service_info_get_interface(info));
+ Gtk::TreeIter iter = m_existing_model->prepend(m_iter_existing_network->children());
+ (*iter)[m_existing_columns.m_col_title] = title;
+ (*iter)[m_existing_columns.m_col_button_text] = _("Open");
+ (*iter)[m_existing_columns.m_col_time] = std::time(NULL); /* sort more recently discovered items above */
+ (*iter)[m_existing_columns.m_col_service_name] = name;
+ (*iter)[m_existing_columns.m_col_service_info] = info;
+
+ epc_service_info_ref(info);
+ g_free(title);
+}
+
+void Dialog_ExistingOrNew::on_service_removed(const Glib::ustring& name, const Glib::ustring& type)
+{
+ // Find the entry with the given name
+ const Gtk::TreeNodeChildren& children = m_iter_existing_network->children();
+ for(Gtk::TreeIter iter = children.begin(); iter != children.end(); ++ iter)
+ {
+ if((*iter)[m_existing_columns.m_col_service_name] == name)
+ {
+ // Remove from store
+ epc_service_info_unref((*iter)[m_existing_columns.m_col_service_info]);
+ m_existing_model->erase(iter);
+ break;
+ }
+ }
+}
+#endif // !G_OS_WIN32
+
+void Dialog_ExistingOrNew::on_existing_row_activated(const Gtk::TreePath& path, Gtk::TreeViewColumn* column)
+{
+ existing_activated(m_existing_model->get_iter(path));
+}
+
+void Dialog_ExistingOrNew::on_existing_button_clicked(const Gtk::TreePath& path)
+{
+ existing_activated(m_existing_model->get_iter(path));
+}
+
+void Dialog_ExistingOrNew::on_new_row_activated(const Gtk::TreePath& path, Gtk::TreeViewColumn* column)
+{
+ new_activated(m_new_model->get_iter(path));
+}
+
+void Dialog_ExistingOrNew::on_new_button_clicked(const Gtk::TreePath& path)
+{
+ new_activated(m_new_model->get_iter(path));
+}
+
+void Dialog_ExistingOrNew::existing_activated(const Gtk::TreeIter& iter)
+{
+ if(iter == m_iter_existing_other)
+ {
+ Gtk::FileChooserDialog dialog(*this, "Choose a glom file to open");
+ Gtk::FileFilter filter;
+ filter.add_mime_type("application/x-glom");
+ filter.set_name("Glom files");
+ dialog.add_filter(filter);
+
+ dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
+ //dialog.set_default_response(Gtk::RESPONSE_ACCEPT);
+
+ if(dialog.run() == Gtk::RESPONSE_ACCEPT)
+ {
+ dialog.hide();
+ m_signal_open_from_uri.emit(dialog.get_uri());
+ response(Gtk::RESPONSE_ACCEPT);
+ }
+ }
+ else if(m_existing_model->is_ancestor(m_iter_existing_recent, iter))
+ {
+ Glib::RefPtr<Gtk::RecentInfo>* info = (*iter)[m_existing_columns.m_col_recent_info];
+ m_signal_open_from_uri.emit((*info)->get_uri());
+ response(Gtk::RESPONSE_ACCEPT);
+ }
+ else if(m_existing_model->is_ancestor(m_iter_existing_network, iter))
+ {
+#ifndef G_OS_WIN32
+ m_signal_open_from_remote.emit((*iter)[m_existing_columns.m_col_service_info], (*iter)[m_existing_columns.m_col_service_name]);
+ response(Gtk::RESPONSE_ACCEPT);
+#endif
+ }
+}
+
+void Dialog_ExistingOrNew::new_activated(const Gtk::TreeIter& iter)
+{
+ if(iter == m_iter_new_empty)
+ {
+ m_signal_new.emit(std::string());
+ response(Gtk::RESPONSE_ACCEPT);
+ }
+ else if(m_new_model->is_ancestor(m_iter_new_template, iter))
+ {
+ m_signal_new.emit((*iter)[m_new_columns.m_col_template_uri]);
+ response(Gtk::RESPONSE_ACCEPT);
+ }
+}
+
+} //namespace Glom
Added: trunk/glom/dialog_existing_or_new.h
==============================================================================
--- (empty file)
+++ trunk/glom/dialog_existing_or_new.h Sun Mar 30 15:16:29 2008
@@ -0,0 +1,185 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * 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.
+ */
+
+#ifndef GLOM_DIALOG_EXISTING_OR_NEW_H
+#define GLOM_DIALOG_EXISTING_OR_NEW_H
+
+#ifndef G_OS_WIN32
+# include <libepc/service-monitor.h>
+#endif
+
+#include <memory>
+#include <giomm/asyncresult.h>
+#include <giomm/file.h>
+#include <giomm/fileenumerator.h>
+#include <giomm/inputstream.h>
+#include <gtkmm/dialog.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/treestore.h>
+#include <gtkmm/recentinfo.h>
+#include <libglademm/xml.h>
+#include <glom/utility_widgets/db_adddel/cellrenderer_buttontext.h>
+
+namespace Glom
+{
+
+class Dialog_ExistingOrNew
+ : public Gtk::Dialog
+{
+ typedef sigc::signal<void, const std::string&> SignalNew;
+ typedef sigc::signal<void, const std::string&> SignalOpenFromUri;
+#ifndef G_OS_WIN32
+ typedef sigc::signal<void, EpcServiceInfo*, const Glib::ustring&> SignalOpenFromRemote;
+#endif
+
+public:
+ Dialog_ExistingOrNew(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& refGlade);
+ virtual ~Dialog_ExistingOrNew();
+
+ SignalNew signal_new() const { return m_signal_new; }
+ SignalOpenFromUri signal_open_from_uri() const { return m_signal_open_from_uri; }
+
+#ifndef G_OS_WIN32
+ SignalOpenFromRemote signal_open_from_remote() const { return m_signal_open_from_remote; }
+#endif
+
+protected:
+ void existing_icon_data_func(Gtk::CellRenderer* renderer, const Gtk::TreeIter& iter);
+ void new_icon_data_func(Gtk::CellRenderer* renderer, const Gtk::TreeIter& iter);
+
+ void on_enumerate_children(const Glib::RefPtr<Gio::AsyncResult>& res);
+ void on_next_files(const Glib::RefPtr<Gio::AsyncResult>& res);
+ void on_read(const Glib::RefPtr<Gio::AsyncResult>& res);
+ void on_stream_read(const Glib::RefPtr<Gio::AsyncResult>& res);
+
+#ifndef G_OS_WIN32
+ static void on_service_found_static(EpcServiceMonitor* monitor, gchar* name, EpcServiceInfo* info, gpointer user_data) { static_cast<Dialog_ExistingOrNew*>(user_data)->on_service_found(name, info); }
+ static void on_service_removed_static(EpcServiceMonitor* monitor, gchar* name, gchar* type, gpointer user_data) { static_cast<Dialog_ExistingOrNew*>(user_data)->on_service_removed(name, type); }
+
+ void on_service_found(const Glib::ustring& name, EpcServiceInfo* info);
+ void on_service_removed(const Glib::ustring& name, const Glib::ustring& type);
+#endif
+
+ void on_existing_row_activated(const Gtk::TreePath& path, Gtk::TreeViewColumn* column);
+ void on_existing_button_clicked(const Gtk::TreePath& path);
+ void on_new_row_activated(const Gtk::TreePath& path, Gtk::TreeViewColumn* column);
+ void on_new_button_clicked(const Gtk::TreePath& path);
+
+ void existing_activated(const Gtk::TreeIter& iter);
+ void new_activated(const Gtk::TreeIter& iter);
+
+ class ExistingModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+
+ ExistingModelColumns()
+ {
+ add(m_col_title);
+ add(m_col_button_text);
+ add(m_col_time);
+
+#ifndef G_OS_WIN32
+ add(m_col_service_name);
+ add(m_col_service_info);
+#endif
+
+ add(m_col_recent_info);
+ }
+
+ Gtk::TreeModelColumn<Glib::ustring> m_col_title;
+ Gtk::TreeModelColumn<Glib::ustring> m_col_button_text;
+ Gtk::TreeModelColumn<std::time_t> m_col_time; // Sort criteria
+
+#ifndef G_OS_WIN32
+ // For service discovery:
+ Gtk::TreeModelColumn<Glib::ustring> m_col_service_name;
+ Gtk::TreeModelColumn<EpcServiceInfo*> m_col_service_info;
+#endif
+
+ // For recently used resources:
+ // TODO: We can't use Glib::RefPtr<Gtk::RecentInfo> directly here, due to
+ // bug #. Therefore, the refptrs are dynamically allocated and explicitely
+ // freed in the destructor.
+ Gtk::TreeModelColumn<Glib::RefPtr<Gtk::RecentInfo>*> m_col_recent_info;
+ };
+
+ class NewModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+
+ NewModelColumns()
+ { add(m_col_title); add(m_col_button_text); add(m_col_template_uri); }
+
+ Gtk::TreeModelColumn<Glib::ustring> m_col_title;
+ Gtk::TreeModelColumn<Glib::ustring> m_col_button_text;
+ Gtk::TreeModelColumn<std::string> m_col_template_uri;
+ };
+
+ ExistingModelColumns m_existing_columns;
+ Glib::RefPtr<Gtk::TreeStore> m_existing_model;
+ Gtk::TreeView* m_existing_view;
+
+ NewModelColumns m_new_columns;
+ Gtk::TreeView* m_new_view;
+ Glib::RefPtr<Gtk::TreeStore> m_new_model;
+
+ Gtk::TreeViewColumn m_existing_column_title;
+ Gtk::TreeViewColumn m_existing_column_button;
+ Gtk::CellRendererPixbuf m_existing_icon_renderer;
+ Gtk::CellRendererText m_existing_title_renderer;
+ GlomCellRenderer_ButtonText m_existing_button_renderer;
+
+ Gtk::TreeViewColumn m_new_column_title;
+ Gtk::TreeViewColumn m_new_column_button;
+ Gtk::CellRendererPixbuf m_new_icon_renderer;
+ Gtk::CellRendererText m_new_title_renderer;
+ GlomCellRenderer_ButtonText m_new_button_renderer;
+
+ Gtk::TreeIter m_iter_existing_recent;
+ Gtk::TreeIter m_iter_existing_network;
+ Gtk::TreeIter m_iter_existing_other;
+
+ Gtk::TreeIter m_iter_new_empty;
+ Gtk::TreeIter m_iter_new_template;
+
+ Glib::RefPtr<Gio::File> m_examples_dir;
+ Glib::RefPtr<Gio::FileEnumerator> m_examples_enumerator;
+ Glib::RefPtr<Gio::File> m_current_example;
+ Glib::RefPtr<Gio::InputStream> m_current_stream;
+
+ struct buffer { static const guint SIZE = 1024; char buf[SIZE]; };
+ std::auto_ptr<buffer> m_current_buffer;
+
+#ifndef G_OS_WIN32
+ EpcServiceMonitor* m_service_monitor;
+#endif
+
+ SignalNew m_signal_new;
+ SignalOpenFromUri m_signal_open_from_uri;
+
+#ifndef G_OS_WIN32
+ SignalOpenFromRemote m_signal_open_from_remote;
+#endif
+};
+
+} //namespace Glom
+
+#endif //GLOM_DIALOG_DATABASE_PREFERENCES_H
+
Modified: trunk/glom/glom.glade
==============================================================================
--- trunk/glom/glom.glade (original)
+++ trunk/glom/glom.glade Sun Mar 30 15:16:29 2008
@@ -193,6 +193,8 @@
</child>
</widget>
<widget class="GtkDialog" id="dialog_existing_or_new">
+ <property name="default_width">480</property>
+ <property name="default_height">320</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
@@ -219,25 +221,24 @@
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="spacing">12</property>
<child>
<widget class="GtkLabel" id="existing_or_new_label">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
- <property name="label" translatable="yes"><span weight="bold" size="larger">Open existing document, or create new document</span>
-
-Would you like to open an existing document, to connect to an existing database?
-
-Or would you like to create a new document, to design a new database?
-</property>
+ <property name="label" translatable="yes"><span weight="bold" size="larger">Please open an existing document or create new document</span></property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
<property name="selectable">True</property>
</widget>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
</child>
<child>
- <widget class="GtkFrame" id="existing_or_new_recentchooser_frame">
+ <widget class="GtkFrame" id="existing_or_new_existing_frame">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label_xalign">0</property>
@@ -246,15 +247,25 @@
<widget class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="top_padding">6</property>
<property name="left_padding">12</property>
<child>
- <widget class="GtkRecentChooserWidget" id="existing_or_new_recentchooser">
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="show_not_found">True</property>
- <property name="show_tips">True</property>
- <property name="sort_type">GTK_RECENT_SORT_MRU</property>
- <property name="limit">15</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <child>
+ <widget class="GtkTreeView" id="existing_or_new_existing_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="headers_clickable">True</property>
+ <property name="search_column">0</property>
+ </widget>
+ </child>
</widget>
</child>
</widget>
@@ -263,7 +274,7 @@
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="label" translatable="yes"><b>Recently Opened Files:</b></property>
+ <property name="label" translatable="yes"><b>Open Existing Document</b></property>
<property name="use_markup">True</property>
</widget>
<packing>
@@ -275,102 +286,77 @@
<property name="position">1</property>
</packing>
</child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <widget class="GtkButton" id="cancelbutton1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- <property name="response_id">-6</property>
- </widget>
- </child>
- <child>
- <widget class="GtkButton" id="existing_or_new_button_new">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="label">gtk-new</property>
- <property name="use_stock">True</property>
- <property name="response_id">2</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="existing_or_new_button_example">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="response_id">3</property>
<child>
- <widget class="GtkAlignment" id="alignment71">
+ <widget class="GtkFrame" id="existing_or_new_new_frame">
<property name="visible">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
<child>
- <widget class="GtkHBox" id="hbox82">
+ <widget class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
- <property name="spacing">2</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
<child>
- <widget class="GtkImage" id="image32">
+ <widget class="GtkScrolledWindow" id="scrolledwindow3">
<property name="visible">True</property>
- <property name="stock">gtk-new</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <child>
+ <widget class="GtkTreeView" id="existing_or_new_new_treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="headers_clickable">True</property>
+ </widget>
+ </child>
</widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label207">
- <property name="visible">True</property>
- <property name="label" translatable="yes">New From Example</property>
- <property name="use_underline">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
</child>
</widget>
</child>
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes"><b>Create New Document</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
</widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
</child>
</widget>
<packing>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
- <widget class="GtkButton" id="button_open">
+ <widget class="GtkButton" id="cancelbutton1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
- <property name="label">gtk-open</property>
+ <property name="label">gtk-close</property>
<property name="use_stock">True</property>
- <property name="response_id">1</property>
+ <property name="response_id">-6</property>
</widget>
- <packing>
- <property name="position">3</property>
- </packing>
</child>
</widget>
<packing>
@@ -449,128 +435,125 @@
<property name="column_spacing">6</property>
<property name="row_spacing">6</property>
<child>
- <widget class="GtkLabel" id="label_database">
+ <widget class="GtkEntry" id="entry_host">
<property name="visible">True</property>
- <property name="xalign">0</property>
+ <property name="can_focus">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label68">
+ <widget class="GtkLabel" id="label64">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">Database</property>
+ <property name="label" translatable="yes">_Host</property>
+ <property name="use_underline">True</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
+ <property name="mnemonic_widget">entry_host</property>
+ <accessibility>
+ <atkrelation target="entry_host" type="label-for"/>
+ </accessibility>
</widget>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label65">
+ <widget class="GtkLabel" id="label66">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">_User</property>
+ <property name="label" translatable="yes">_Password</property>
<property name="use_underline">True</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
- <property name="mnemonic_widget">entry_user</property>
+ <property name="mnemonic_widget">entry_password</property>
<accessibility>
- <atkrelation target="entry_user" type="label-for"/>
+ <atkrelation target="entry_password" type="label-for"/>
</accessibility>
</widget>
<packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkEntry" id="entry_user">
+ <widget class="GtkEntry" id="entry_password">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="invisible_char">*</property>
+ <property name="has_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="activates_default">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkEntry" id="entry_password">
+ <widget class="GtkEntry" id="entry_user">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="visibility">False</property>
- <property name="invisible_char">*</property>
- <property name="activates_default">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label66">
+ <widget class="GtkLabel" id="label65">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">_Password</property>
+ <property name="label" translatable="yes">_User</property>
<property name="use_underline">True</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
- <property name="mnemonic_widget">entry_password</property>
+ <property name="mnemonic_widget">entry_user</property>
<accessibility>
- <atkrelation target="entry_password" type="label-for"/>
+ <atkrelation target="entry_user" type="label-for"/>
</accessibility>
</widget>
<packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label64">
+ <widget class="GtkLabel" id="label68">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">_Host</property>
- <property name="use_underline">True</property>
+ <property name="label" translatable="yes">Database</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
- <property name="mnemonic_widget">entry_host</property>
- <accessibility>
- <atkrelation target="entry_host" type="label-for"/>
- </accessibility>
</widget>
<packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkEntry" id="entry_host">
+ <widget class="GtkLabel" id="label_database">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">*</property>
+ <property name="xalign">0</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
@@ -930,7 +913,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
- <property name="invisible_char">*</property>
<property name="activates_default">True</property>
</widget>
<packing>
@@ -1141,7 +1123,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="has_focus">True</property>
- <property name="invisible_char">*</property>
</widget>
<packing>
<property name="position">1</property>
@@ -1249,9 +1230,12 @@
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label_records_count">
+ <widget class="GtkButton" id="button_find_all">
<property name="visible">True</property>
- <property name="label" translatable="yes">0</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Find All</property>
+ <property name="use_underline">True</property>
+ <property name="response_id">0</property>
</widget>
<packing>
<property name="expand">False</property>
@@ -1261,12 +1245,9 @@
</packing>
</child>
<child>
- <widget class="GtkButton" id="button_find_all">
+ <widget class="GtkLabel" id="label_records_count">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Find All</property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
+ <property name="label" translatable="yes">0</property>
</widget>
<packing>
<property name="expand">False</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]