[gnote] Sticky Notes import addin.
- From: Hubert Figuière <hub src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnote] Sticky Notes import addin.
- Date: Fri, 29 May 2009 00:31:29 -0400 (EDT)
commit 10449d80a28e1240353e02ecc52535786442b22c
Author: Hubert Figuiere <hub figuiere net>
Date: Thu May 28 18:28:46 2009 -0400
Sticky Notes import addin.
---
NEWS | 2 +
configure.ac | 1 +
src/addins/Makefile.am | 1 +
src/addins/stickynoteimport/Makefile.am | 9 +
.../stickynoteimport/stickynoteimportnoteaddin.cpp | 297 ++++++++++++++++++++
.../stickynoteimport/stickynoteimportnoteaddin.hpp | 94 ++++++
src/sharp/files.cpp | 21 ++-
src/sharp/files.hpp | 9 +-
8 files changed, 428 insertions(+), 6 deletions(-)
diff --git a/NEWS b/NEWS
index d560927..7807ba0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,5 @@
+ * Sticky Notes import addin.
+
0.5.0 -
Fixes:
diff --git a/configure.ac b/configure.ac
index 1aadc32..93f7d22 100644
--- a/configure.ac
+++ b/configure.ac
@@ -214,6 +214,7 @@ src/addins/exporttohtml/Makefile
src/addins/fixedwidth/Makefile
src/addins/inserttimestamp/Makefile
src/addins/printnotes/Makefile
+src/addins/stickynoteimport/Makefile
po/Makefile.in
po/Makefile
help/Makefile
diff --git a/src/addins/Makefile.am b/src/addins/Makefile.am
index 0306d8b..045849d 100644
--- a/src/addins/Makefile.am
+++ b/src/addins/Makefile.am
@@ -7,4 +7,5 @@ SUBDIRS = backlinks \
fixedwidth \
inserttimestamp \
printnotes \
+ stickynoteimport \
$(NULL)
\ No newline at end of file
diff --git a/src/addins/stickynoteimport/Makefile.am b/src/addins/stickynoteimport/Makefile.am
new file mode 100644
index 0000000..9edada0
--- /dev/null
+++ b/src/addins/stickynoteimport/Makefile.am
@@ -0,0 +1,9 @@
+
+include $(builddir)/../addins.mk
+
+addinsdir = $(ADDINSDIR)
+addins_LTLIBRARIES = stickynoteimport.la
+
+
+stickynoteimport_la_SOURCES = stickynoteimportnoteaddin.hpp stickynoteimportnoteaddin.cpp \
+ $(NULL)
diff --git a/src/addins/stickynoteimport/stickynoteimportnoteaddin.cpp b/src/addins/stickynoteimport/stickynoteimportnoteaddin.cpp
new file mode 100644
index 0000000..008a56b
--- /dev/null
+++ b/src/addins/stickynoteimport/stickynoteimportnoteaddin.cpp
@@ -0,0 +1,297 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * 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 <boost/format.hpp>
+
+#include <glibmm/i18n.h>
+#include <gtkmm/image.h>
+#include <gtkmm/stock.h>
+
+#include "stickynoteimportnoteaddin.hpp"
+#include "sharp/files.hpp"
+#include "sharp/string.hpp"
+#include "sharp/xml.hpp"
+#include "debug.hpp"
+#include "note.hpp"
+#include "notemanager.hpp"
+#include "notewindow.hpp"
+#include "preferences.hpp"
+#include "utils.hpp"
+
+namespace stickynote {
+
+ using gnote::Preferences;
+ using gnote::Note;
+
+
+StickNoteImportModule::StickNoteImportModule()
+{
+ ADD_INTERFACE_IMPL(StickNoteImportNoteAddin);
+}
+const char * StickNoteImportModule::id() const
+{
+ return "StickNoteImportAddin";
+}
+const char * StickNoteImportModule::name() const
+{
+ return _("Sticky Notes Importer");
+}
+const char * StickNoteImportModule::description() const
+{
+ return _("Import your notes from the Sticky Notes applet.");
+}
+const char * StickNoteImportModule::authors() const
+{
+ return _("Hubert Figuiere and the Tomboy Project");
+}
+const char * StickNoteImportModule::category() const
+{
+ return "Tools";
+}
+const char * StickNoteImportModule::version() const
+{
+ return "0.1";
+}
+
+static const char * STICKY_XML_REL_PATH = "/.gnome2/stickynotes_applet";
+static const char * STICKY_NOTE_QUERY = "//note";
+static const char * DEBUG_NO_STICKY_FILE = "StickyNoteImporter: Sticky Notes XML file does not exist or is invalid!";
+static const char * DEBUG_CREATE_ERROR_BASE = "StickyNoteImporter: Error while trying to create note \"%s\": %s";
+static const char * DEBUG_FIRST_RUN_DETECTED = "StickyNoteImporter: Detecting that importer has never been run...";
+//static const char * DEBUG_GCONF_SET_ERROR_BASE = "StickyNoteImporter: Error setting initial GConf first run key value: %s";
+
+
+bool StickNoteImportNoteAddin::s_static_inited = false;
+bool StickNoteImportNoteAddin::s_sticky_file_might_exist = true;
+bool StickNoteImportNoteAddin::s_sticky_file_existence_confirmed = false;
+std::string StickNoteImportNoteAddin::s_sticky_xml_path;
+
+
+void StickNoteImportNoteAddin::_init_static()
+{
+ if(!s_static_inited) {
+ s_sticky_xml_path = Glib::get_home_dir() + STICKY_XML_REL_PATH;
+ s_static_inited = true;
+ }
+}
+
+void StickNoteImportNoteAddin::initialize()
+{
+ // Don't add item to tools menu if Sticky Notes XML file does not
+ // exist. Only check for the file once, since Initialize is called
+ // for each note when Tomboy starts up.
+ if (s_sticky_file_might_exist) {
+ if (s_sticky_file_existence_confirmed || sharp::file_exists (s_sticky_xml_path)) {
+ m_item = manage(new Gtk::ImageMenuItem (_("Import from Sticky Notes")));
+ m_item->set_image(*manage(new Gtk::Image (Gtk::Stock::CONVERT, Gtk::ICON_SIZE_MENU)));
+ m_item->signal_activate().connect(
+ sigc::mem_fun(*this, &StickNoteImportNoteAddin::import_button_clicked));
+ m_item->show ();
+ add_plugin_menu_item (m_item);
+
+ s_sticky_file_existence_confirmed = true;
+ check_for_first_run();
+ }
+ else {
+ s_sticky_file_might_exist = false;
+ DBG_OUT(DEBUG_NO_STICKY_FILE);
+ }
+ }
+
+}
+
+
+
+void StickNoteImportNoteAddin::shutdown()
+{
+}
+
+
+void StickNoteImportNoteAddin::on_note_opened()
+{
+}
+
+
+void StickNoteImportNoteAddin::check_for_first_run()
+{
+ bool firstRun = Preferences::obj().get<bool> (Preferences::STICKYNOTEIMPORTER_FIRST_RUN);
+
+ if (firstRun) {
+ Preferences::obj().set<bool> (Preferences::STICKYNOTEIMPORTER_FIRST_RUN, false);
+
+ DBG_OUT(DEBUG_FIRST_RUN_DETECTED);
+
+ xmlDocPtr xml_doc = get_sticky_xml_doc();
+ if (xml_doc) {
+ // Don't show dialog when automatically importing
+ import_notes (xml_doc, false);
+ xmlFreeDoc(xml_doc);
+ }
+ }
+
+}
+
+
+xmlDocPtr StickNoteImportNoteAddin::get_sticky_xml_doc()
+{
+ if (sharp::file_exists(s_sticky_xml_path)) {
+ xmlDocPtr xml_doc = xmlReadFile(s_sticky_xml_path.c_str(), "UTF-8", 0);
+ if(xml_doc == NULL) {
+ DBG_OUT(DEBUG_NO_STICKY_FILE);
+ }
+ return xml_doc;
+ }
+ else {
+ DBG_OUT(DEBUG_NO_STICKY_FILE);
+ return NULL;
+ }
+}
+
+
+void StickNoteImportNoteAddin::import_button_clicked()
+{
+ xmlDocPtr xml_doc = get_sticky_xml_doc();
+ if(xml_doc) {
+ import_notes (xml_doc, true);
+ }
+ else {
+ show_no_sticky_xml_dialog(s_sticky_xml_path);
+ }
+}
+
+
+void StickNoteImportNoteAddin::show_no_sticky_xml_dialog(const std::string & xml_path)
+{
+ show_message_dialog (
+ _("No Sticky Notes found"),
+ // %1% is a the file name
+ str(boost::format(_("No suitable Sticky Notes file was found at \"%1%\"."))
+ % xml_path), Gtk::MESSAGE_ERROR);
+}
+
+
+void StickNoteImportNoteAddin::show_results_dialog(int numNotesImported, int numNotesTotal)
+{
+ show_message_dialog (
+ _("Sticky Notes import completed"),
+ // here %1% is the number of notes imported, %2% the total number of notes.
+ str(boost::format(_("<b>%1%</b> of <b>%s%</b> Sticky Notes "
+ "were successfully imported."))
+ % numNotesImported % numNotesTotal), Gtk::MESSAGE_INFO);
+}
+
+
+void StickNoteImportNoteAddin::import_notes(xmlDocPtr xml_doc, bool showResultsDialog)
+{
+ xmlNodePtr root_node = xmlDocGetRootElement(xml_doc);
+ if(!root_node) {
+ if (showResultsDialog)
+ show_no_sticky_xml_dialog(s_sticky_xml_path);
+ return;
+ }
+ sharp::XmlNodeSet nodes = sharp::xml_node_xpath_find(root_node, STICKY_NOTE_QUERY);
+
+ int numSuccessful = 0;
+ const xmlChar * defaultTitle = (const xmlChar *)_("Untitled");
+
+ for(sharp::XmlNodeSet::const_iterator iter = nodes.begin();
+ iter != nodes.end(); ++iter) {
+
+ xmlNodePtr node = *iter;
+ const xmlChar * stickyTitle;
+ xmlChar * titleAttr = xmlGetProp(node, (const xmlChar*)"title");
+ if(titleAttr) {
+ stickyTitle = titleAttr;
+ }
+ else {
+ stickyTitle = defaultTitle;
+ }
+ xmlChar * stickyContent = xmlNodeGetContent(node);
+
+ if(stickyContent) {
+ if (create_note_from_sticky ((const char*)stickyTitle, (const char*)stickyContent)) {
+ numSuccessful++;
+ }
+ xmlFree(stickyContent);
+ }
+
+ if(titleAttr) {
+ xmlFree(titleAttr);
+ }
+ }
+
+ if (showResultsDialog) {
+ show_results_dialog (numSuccessful, nodes.size());
+ }
+}
+
+
+bool StickNoteImportNoteAddin::create_note_from_sticky(const char * stickyTitle,
+ const char* content)
+{
+ // There should be no XML in the content
+ // TODO: Report the error in the results dialog
+ // (this error should only happen if somebody has messed with the XML file)
+ if(strchr(content, '>') || strchr(content, '<')) {
+ DBG_OUT(DEBUG_CREATE_ERROR_BASE, stickyTitle,
+ "Invalid characters in note XML");
+ return false;
+ }
+
+ std::string preferredTitle = _("Sticky Note: ");
+ preferredTitle += stickyTitle;
+ std::string title = preferredTitle;
+
+ int i = 2; // Append numbers to create unique title, starting with 2
+ while (manager().find(title)){
+ title = str(boost::format("%1% (#%2%)") % preferredTitle % i);
+ i++;
+ }
+
+ std::string noteXml = str(boost::format("<note-content><note-title>%1%</note-title>\n\n"
+ "%2%</note-content>") % title % content);
+
+ try {
+ Note::Ptr newNote = manager().create(title, noteXml);
+ newNote->queue_save (Note::NO_CHANGE);
+ newNote->save();
+ return true;
+ }
+ catch (const std::exception & e) {
+ DBG_OUT(DEBUG_CREATE_ERROR_BASE, title.c_str(), e.what());
+ return false;
+ }
+}
+
+
+void StickNoteImportNoteAddin::show_message_dialog(const std::string & title,
+ const std::string & message,
+ Gtk::MessageType messageType)
+{
+ gnote::utils::HIGMessageDialog dialog(get_window(),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ messageType,
+ Gtk::BUTTONS_OK,
+ title,
+ message);
+ dialog.run();
+}
+
+
+}
diff --git a/src/addins/stickynoteimport/stickynoteimportnoteaddin.hpp b/src/addins/stickynoteimport/stickynoteimportnoteaddin.hpp
new file mode 100644
index 0000000..4374ddf
--- /dev/null
+++ b/src/addins/stickynoteimport/stickynoteimportnoteaddin.hpp
@@ -0,0 +1,94 @@
+/*
+ * gnote
+ *
+ * Copyright (C) 2009 Hubert Figuiere
+ *
+ * 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/>.
+ */
+
+#ifndef __STICKYNOTE_IMPORT_NOTE_ADDIN_HPP_
+#define __STICKYNOTE_IMPORT_NOTE_ADDIN_HPP_
+
+#include <string>
+
+#include <libxml/tree.h>
+
+#include <gtkmm/imagemenuitem.h>
+
+#include "sharp/dynamicmodule.hpp"
+#include "noteaddin.hpp"
+
+namespace stickynote {
+
+
+class StickNoteImportModule
+ : public sharp::DynamicModule
+{
+public:
+ StickNoteImportModule();
+ virtual const char * id() const;
+ virtual const char * name() const;
+ virtual const char * description() const;
+ virtual const char * authors() const;
+ virtual const char * category() const;
+ virtual const char * version() const;
+};
+
+
+DECLARE_MODULE(StickNoteImportModule);
+
+class StickNoteImportNoteAddin
+ : public gnote::NoteAddin
+{
+public:
+
+ static StickNoteImportNoteAddin * create()
+ {
+ return new StickNoteImportNoteAddin;
+ }
+
+ StickNoteImportNoteAddin()
+ {
+ _init_static();
+ }
+ virtual void initialize();
+ virtual void shutdown();
+ virtual void on_note_opened();
+
+private:
+ void check_for_first_run();
+ xmlDocPtr get_sticky_xml_doc();
+ void import_button_clicked();
+ void show_no_sticky_xml_dialog(const std::string & xml_path);
+ void show_results_dialog(int numNotesImported, int numNotesTotal);
+ void import_notes(xmlDocPtr xml_doc, bool showResultsDialog);
+ bool create_note_from_sticky(const char * stickyTitle, const char* content);
+ void show_message_dialog(const std::string & title, const std::string & message,
+ Gtk::MessageType messageType);
+
+ Gtk::ImageMenuItem *m_item;
+
+ static void _init_static();
+ static bool s_static_inited;
+ static bool s_sticky_file_might_exist;
+ static bool s_sticky_file_existence_confirmed;
+ static std::string s_sticky_xml_path;
+};
+
+
+}
+
+
+#endif
+
diff --git a/src/sharp/files.cpp b/src/sharp/files.cpp
index 1035e7a..d15cb32 100644
--- a/src/sharp/files.cpp
+++ b/src/sharp/files.cpp
@@ -22,8 +22,6 @@
* DEALINGS IN THE SOFTWARE.
*/
-
-
#include <boost/version.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/convenience.hpp>
@@ -34,6 +32,14 @@
namespace sharp {
+ bool file_exists(const std::string & file)
+ {
+ boost::filesystem::path p(file);
+ // is_regular_file isn't in 1.34. is_regular is deprecated.
+ return (exists(p) && is_regular(p));
+ }
+
+
std::string file_basename(const std::string & p)
{
#if BOOST_VERSION >= 103600
@@ -48,6 +54,12 @@ namespace sharp {
return boost::filesystem::path(p).branch_path().string();
}
+
+ std::string file_filename(const std::string & p)
+ {
+ return boost::filesystem::path(p).leaf();
+ }
+
void file_delete(const std::string & p)
{
boost::filesystem::remove(p);
@@ -59,6 +71,9 @@ namespace sharp {
boost::filesystem::copy_file(source, dest);
}
-
+ void file_move(const std::string & from, const std::string & to)
+ {
+ boost::filesystem::rename(from, to);
+ }
}
diff --git a/src/sharp/files.hpp b/src/sharp/files.hpp
index 7f0c1ba..b5e19c2 100644
--- a/src/sharp/files.hpp
+++ b/src/sharp/files.hpp
@@ -22,9 +22,6 @@
* DEALINGS IN THE SOFTWARE.
*/
-
-
-
#ifndef __SHARP_FILES_HPP_
#define __SHARP_FILES_HPP_
@@ -32,9 +29,15 @@
namespace sharp {
+ bool file_exists(const std::string & p);
void file_delete(const std::string & p);
+ void file_move(const std::string & from, const std::string & to);
+ /** return the basename of the file path */
std::string file_basename(const std::string & p);
+ /** return the directory from the file path */
std::string file_dirname(const std::string & p);
+ /** return the filename from the file path */
+ std::string file_filename(const std::string & p);
void file_copy(const std::string & source, const std::string & dest);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]