r18801 - gnucash/trunk/src - Some more C++ work. Opening an existing file works, even though nothing is visible so far.
Christian Stimming
cstim at code.gnucash.org
Wed Mar 3 15:47:31 EST 2010
Author: cstim
Date: 2010-03-03 15:47:31 -0500 (Wed, 03 Mar 2010)
New Revision: 18801
Trac: http://svn.gnucash.org/trac/changeset/18801
Added:
gnucash/trunk/src/gnc/Account.hpp
gnucash/trunk/src/gnc/Book.cpp
gnucash/trunk/src/gnc/Book.hpp
gnucash/trunk/src/gnc/ScopedPointer.hpp
gnucash/trunk/src/gnc/Session.cpp
gnucash/trunk/src/gnc/Session.hpp
gnucash/trunk/src/gnc/WeakPointer.hpp
Modified:
gnucash/trunk/src/CMakeLists.txt
gnucash/trunk/src/gnc/CMakeLists.txt
gnucash/trunk/src/gnc/mainwindow.cpp
gnucash/trunk/src/gnc/mainwindow.hpp
Log:
Some more C++ work. Opening an existing file works, even though nothing is visible so far.
The implementation of a scoped_ptr wrapper around a C object
uses the boost library, though, because writing our own
implementation of a scoped_ptr with custom deletion function
is too non-trivial and I rather re-use the boost::shared_ptr
here instead of making our own mistakes.
Modified: gnucash/trunk/src/CMakeLists.txt
===================================================================
--- gnucash/trunk/src/CMakeLists.txt 2010-03-03 20:47:10 UTC (rev 18800)
+++ gnucash/trunk/src/CMakeLists.txt 2010-03-03 20:47:31 UTC (rev 18801)
@@ -65,6 +65,22 @@
SET (QT_MIN_VERSION "4.5.0")
FIND_PACKAGE (Qt4 REQUIRED) # find and setup Qt4 for this project
+# ############################################################
+
+# Check for boost
+FIND_PACKAGE (Boost QUIET)
+INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS})
+
+# MSVC should not link against boost-regex and boost-date_time.
+IF (MSVC)
+ ADD_DEFINITIONS( -DBOOST_ALL_NO_LIB )
+ENDIF (MSVC)
+IF (WIN32)
+ ADD_DEFINITIONS (-DWIN32_LEAN_AND_MEAN)
+ENDIF (WIN32)
+
+# ############################################################
+
# Compiler flags
IF (UNIX)
SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wdeclaration-after-statement -Wno-pointer-sign -D_FORTIFY_SOURCE=2 -Wall -Wunused -Wmissing-prototypes -Wmissing-declarations -Wno-unused")
Added: gnucash/trunk/src/gnc/Account.hpp
===================================================================
--- gnucash/trunk/src/gnc/Account.hpp (rev 0)
+++ gnucash/trunk/src/gnc/Account.hpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,27 @@
+#ifndef GNC_ACCOUNT_HPP
+#define GNC_ACCOUNT_HPP
+
+// gnucash includes
+extern "C"
+{
+#include "qof.h"
+#include "engine/Account.h"
+}
+
+#include "gnc/WeakPointer.hpp"
+
+namespace gnc
+{
+
+class Account : public WeakPointer< ::Account >
+{
+public:
+ typedef WeakPointer< ::Account > base_class;
+ Account(element_type* ptr = 0)
+ : base_class(ptr)
+ { }
+};
+
+} // END namespace gnc
+
+#endif
Added: gnucash/trunk/src/gnc/Book.cpp
===================================================================
--- gnucash/trunk/src/gnc/Book.cpp (rev 0)
+++ gnucash/trunk/src/gnc/Book.cpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,12 @@
+#include "config.h"
+#include "gnc/Book.hpp"
+#include "gnc/Account.hpp"
+
+namespace gnc
+{
+Account Book::get_root_account()
+{
+ return Account(gnc_book_get_root_account (get()));
+}
+
+} // END namespace gnc
Added: gnucash/trunk/src/gnc/Book.hpp
===================================================================
--- gnucash/trunk/src/gnc/Book.hpp (rev 0)
+++ gnucash/trunk/src/gnc/Book.hpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,31 @@
+#ifndef GNC_BOOK_HPP
+#define GNC_BOOK_HPP
+
+// gnucash includes
+extern "C"
+{
+#include "qof.h"
+#include "engine/gnc-hooks.h"
+#include "engine/Account.h"
+}
+
+#include "gnc/WeakPointer.hpp"
+
+namespace gnc
+{
+class Account;
+
+class Book : public WeakPointer< ::QofBook >
+{
+public:
+ typedef WeakPointer< ::QofBook > base_class;
+ Book(element_type* ptr = 0)
+ : base_class(ptr)
+ { }
+
+ Account get_root_account();
+};
+
+} // END namespace gnc
+
+#endif
Modified: gnucash/trunk/src/gnc/CMakeLists.txt
===================================================================
--- gnucash/trunk/src/gnc/CMakeLists.txt 2010-03-03 20:47:10 UTC (rev 18800)
+++ gnucash/trunk/src/gnc/CMakeLists.txt 2010-03-03 20:47:31 UTC (rev 18801)
@@ -10,6 +10,8 @@
)
SET (gnc_SOURCES
+ Book.cpp
+ Session.cpp
main.cpp
mainwindow.cpp
)
@@ -18,6 +20,11 @@
mainwindow.hpp
)
SET (gnc_HEADERS ${gnc_QOBJECT_HEADERS}
+ Account.hpp
+ Book.hpp
+ ScopedPointer.hpp
+ Session.hpp
+ WeakPointer.hpp
)
SET (gnc_FORMS
Added: gnucash/trunk/src/gnc/ScopedPointer.hpp
===================================================================
--- gnucash/trunk/src/gnc/ScopedPointer.hpp (rev 0)
+++ gnucash/trunk/src/gnc/ScopedPointer.hpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,83 @@
+#ifndef GNC_SCOPEDPOINTER_HPP
+#define GNC_SCOPEDPOINTER_HPP
+
+#include <boost/shared_ptr.hpp>
+
+namespace gnc
+{
+
+/** A sole ownership of a single C object.
+ *
+ * This copies the interface of the boost::scoped_ptr, but with the
+ * boost::shared_ptr possiblity of a custom deleter function because
+ * we need that.
+ */
+template<class T>
+class ScopedPointer // noncopyable
+{
+ // Private copy constructor so that this is noncopyable
+ ScopedPointer(ScopedPointer const &);
+ ScopedPointer& operator=(ScopedPointer const&);
+ void operator==(ScopedPointer const&) const;
+ void operator!=(ScopedPointer const&) const;
+ boost::shared_ptr<T> m_ptr;
+ typedef ScopedPointer<T> this_type;
+public:
+ typedef T element_type;
+
+ ScopedPointer()
+ : m_ptr()
+ { }
+
+ template<class Y, class D> ScopedPointer(Y * ptr, D deleter)
+ : m_ptr(ptr, deleter)
+ { }
+
+ void reset() // never throws in 1.30+
+ {
+ this_type().swap(*this);
+ }
+
+ template<class Y, class D> void reset( Y * p, D d )
+ {
+ this_type( p, d ).swap( *this );
+ }
+
+ T & operator*() const // never throws
+ {
+ assert(m_ptr != 0);
+ return *m_ptr.get();
+ }
+
+ T * operator->() const // never throws
+ {
+ assert(m_ptr != 0);
+ return m_ptr.get();
+ }
+
+ T * get() const // never throws
+ {
+ return m_ptr.get();
+ }
+
+ // implicit conversion to "bool"
+ typedef T * (this_type::*unspecified_bool_type)() const;
+ operator unspecified_bool_type() const // never throws
+ {
+ return m_ptr == 0? 0: &this_type::get;
+ }
+
+ bool operator! () const // never throws
+ {
+ return m_ptr == 0;
+ }
+
+ void swap(ScopedPointer & other) // never throws
+ {
+ m_ptr.swap(other.m_ptr);
+ }
+};
+
+} // END namespace gnc
+
+#endif
Added: gnucash/trunk/src/gnc/Session.cpp
===================================================================
--- gnucash/trunk/src/gnc/Session.cpp (rev 0)
+++ gnucash/trunk/src/gnc/Session.cpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,83 @@
+#include "config.h"
+#include "gnc/Session.hpp"
+#include "gnc/Book.hpp"
+
+// Explicit instantiation to check for compiler errors in the template
+template class gnc::ScopedPointer< QofSession >;
+template class gnc::WeakPointer< QofSession >;
+
+
+namespace gnc
+{
+
+Book Session::get_book () const
+{
+ return Book(qof_session_get_book(get()));
+}
+
+
+#define TYPE_TO_STR(tstr, desc) tstr : return std::make_pair<std::string,std::string>(#tstr, desc)
+
+std::pair<std::string, std::string> errorToStringPair(QofBackendError err)
+{
+ switch (err)
+ {
+ case TYPE_TO_STR(ERR_BACKEND_NO_ERR, "No Error");
+ case TYPE_TO_STR(ERR_BACKEND_NO_HANDLER, "no backend handler found for this access method (ENOSYS)");
+ case TYPE_TO_STR(ERR_BACKEND_NO_BACKEND, "Backend * pointer was unexpectedly null");
+ case TYPE_TO_STR(ERR_BACKEND_BAD_URL, "Can't parse url");
+ case TYPE_TO_STR(ERR_BACKEND_NO_SUCH_DB, "the named database doesn't exist");
+ case TYPE_TO_STR(ERR_BACKEND_CANT_CONNECT, "bad dbname/login/passwd or network failure");
+ case TYPE_TO_STR(ERR_BACKEND_CONN_LOST, "Lost connection to server");
+ case TYPE_TO_STR(ERR_BACKEND_LOCKED, "in use by another user (ETXTBSY)");
+ case TYPE_TO_STR(ERR_BACKEND_READONLY, "cannot write to file/directory");
+ case TYPE_TO_STR(ERR_BACKEND_TOO_NEW, "file/db version newer than what we can read");
+ case TYPE_TO_STR(ERR_BACKEND_DATA_CORRUPT, "data in db is corrupt");
+ case TYPE_TO_STR(ERR_BACKEND_SERVER_ERR, "error in response from server");
+ case TYPE_TO_STR(ERR_BACKEND_ALLOC, "internal memory allocation failure");
+ case TYPE_TO_STR(ERR_BACKEND_PERM, "user login successful, but no permissions to access the desired object");
+ case TYPE_TO_STR(ERR_BACKEND_MODIFIED, "commit of object update failed because another user has modified the object");
+ case TYPE_TO_STR(ERR_BACKEND_MOD_DESTROY, "commit of object update failed because another user has deleted the object");
+ case TYPE_TO_STR(ERR_BACKEND_MISC, "undetermined error");
+ case TYPE_TO_STR(ERR_QSF_INVALID_OBJ, "The QSF object failed to validate against the QSF object schema");
+ case TYPE_TO_STR(ERR_QSF_INVALID_MAP, "The QSF map failed to validate against the QSF map schema");
+ case TYPE_TO_STR(ERR_QSF_BAD_OBJ_GUID, "The QSF object contains one or more invalid GUIDs.");
+ case TYPE_TO_STR(ERR_QSF_BAD_QOF_VERSION, "QSF map or object doesn't match the current QOF_OBJECT_VERSION.");
+ case TYPE_TO_STR(ERR_QSF_BAD_MAP, "The selected map validates but is unusable.");
+ case TYPE_TO_STR(ERR_QSF_NO_MAP, "The QSF object file was loaded without a map");
+ case TYPE_TO_STR(ERR_QSF_WRONG_MAP, "The selected map validates but is for different objects.");
+ case TYPE_TO_STR(ERR_QSF_MAP_NOT_OBJ, "Selected file is a QSF map and cannot be opened as a QSF object");
+ case TYPE_TO_STR(ERR_QSF_OVERFLOW, "EOVERFLOW - generated by strtol or strtoll.");
+ case TYPE_TO_STR(ERR_QSF_OPEN_NOT_MERGE, "QSF files cannot be opened alone. The data must be merged.");
+ case TYPE_TO_STR(ERR_FILEIO_FILE_BAD_READ, "read failed or file prematurely truncated");
+ case TYPE_TO_STR(ERR_FILEIO_FILE_EMPTY, "file exists, is readable, but is empty");
+ case TYPE_TO_STR(ERR_FILEIO_FILE_LOCKERR, "mangled locks (unspecified error)");
+ case TYPE_TO_STR(ERR_FILEIO_FILE_NOT_FOUND, "not found / no such file");
+ case TYPE_TO_STR(ERR_FILEIO_FILE_TOO_OLD, "file version so old we can't read it");
+ case TYPE_TO_STR(ERR_FILEIO_UNKNOWN_FILE_TYPE, "didn't recognize the file type");
+ case TYPE_TO_STR(ERR_FILEIO_PARSE_ERROR, "couldn't parse the data in the file");
+ case TYPE_TO_STR(ERR_FILEIO_BACKUP_ERROR, "couldn't make a backup of the file");
+ case TYPE_TO_STR(ERR_FILEIO_WRITE_ERROR, "couldn't write to the file");
+ case TYPE_TO_STR(ERR_FILEIO_READ_ERROR, "Could not open the file for reading.");
+ case TYPE_TO_STR(ERR_FILEIO_NO_ENCODING, "file does not specify encoding");
+ case TYPE_TO_STR(ERR_FILEIO_FILE_EACCES, "No read access permission for the given file");
+ case TYPE_TO_STR(ERR_NETIO_SHORT_READ, "not enough bytes received");
+ case TYPE_TO_STR(ERR_NETIO_WRONG_CONTENT_TYPE, "wrong kind of server, wrong data served");
+ case TYPE_TO_STR(ERR_NETIO_NOT_GNCXML, "whatever it is, we can't parse it.");
+ case TYPE_TO_STR(ERR_SQL_MISSING_DATA, "database doesn't contain expected data");
+ case TYPE_TO_STR(ERR_SQL_DB_TOO_OLD, "database is old and needs upgrading");
+ case TYPE_TO_STR(ERR_SQL_DB_BUSY, "database is busy, cannot upgrade version");
+ case TYPE_TO_STR(ERR_RPC_HOST_UNK, "Host unknown");
+ case TYPE_TO_STR(ERR_RPC_CANT_BIND, "can't bind to address");
+ case TYPE_TO_STR(ERR_RPC_CANT_ACCEPT, "can't accept connection");
+ case TYPE_TO_STR(ERR_RPC_NO_CONNECTION, "no connection to server");
+ case TYPE_TO_STR(ERR_RPC_BAD_VERSION, "RPC Version Mismatch");
+ case TYPE_TO_STR(ERR_RPC_FAILED, "Operation failed");
+ case TYPE_TO_STR(ERR_RPC_NOT_ADDED, "object not added");
+ default:
+ assert(0); // must not be reached
+ return std::make_pair("Unknown", "Unknown");
+ }
+}
+
+} // END namespace gnc
Added: gnucash/trunk/src/gnc/Session.hpp
===================================================================
--- gnucash/trunk/src/gnc/Session.hpp (rev 0)
+++ gnucash/trunk/src/gnc/Session.hpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,107 @@
+#ifndef GNC_SESSION_HPP
+#define GNC_SESSION_HPP
+
+// gnucash includes
+#include "config.h" // required by qof/qofutil.h
+extern "C"
+{
+#include <glib/gi18n.h>
+#include "qof.h"
+#include "engine/gnc-hooks.h"
+}
+
+#include "gnc/ScopedPointer.hpp"
+#include <boost/noncopyable.hpp>
+#include <string>
+
+namespace gnc
+{
+
+class Book;
+
+/** ScopedPointer object around a QofSession object, which also owns the
+ * QofSession object.
+ */
+class Session : public ScopedPointer< ::QofSession >
+ , boost::noncopyable
+{
+public:
+ typedef ScopedPointer< ::QofSession > base_class;
+
+ Session()
+ : base_class()
+ {}
+ Session(element_type *ptr)
+ : base_class(ptr, qof_session_destroy)
+ {}
+ void reset(element_type *ptr)
+ {
+ base_class::reset(ptr, qof_session_destroy);
+ }
+ using base_class::reset;
+ static element_type* newInstance()
+ {
+ return qof_session_new();
+ }
+
+ // Now the actual functions on the object
+
+ void begin(const std::string& book_id, bool ignore_lock, bool create_if_nonexistent)
+ {
+ qof_session_begin(get(), book_id.c_str(), ignore_lock, create_if_nonexistent);
+ }
+ void load (QofPercentageFunc percentage_func)
+ {
+ qof_session_load(get(), percentage_func);
+ }
+ QofBackendError get_error ()
+ {
+ return qof_session_get_error(get());
+ }
+ QofBackendError pop_error ()
+ {
+ return qof_session_pop_error(get());
+ }
+ std::string get_error_message() const
+ {
+ return qof_session_get_error_message(get());
+ }
+ Book get_book () const;
+
+ std::string get_file_path () const
+ {
+ return qof_session_get_file_path(get());
+ }
+
+ std::string get_url() const
+ {
+ return qof_session_get_url(get());
+ }
+
+ bool save_in_progress() const
+ {
+ return qof_session_save_in_progress(get());
+ }
+ bool save_may_clobber_data () const
+ {
+ return qof_session_save_may_clobber_data(get());
+ }
+ void save (QofPercentageFunc percentage_func)
+ {
+ qof_session_save(get(), percentage_func);
+ }
+
+
+ void call_close_hooks ()
+ {
+ qof_session_call_close_hooks (get());
+ }
+
+
+};
+
+std::pair<std::string, std::string> errorToStringPair(QofBackendError err);
+
+} // END namespace gnc
+
+#endif
Added: gnucash/trunk/src/gnc/WeakPointer.hpp
===================================================================
--- gnucash/trunk/src/gnc/WeakPointer.hpp (rev 0)
+++ gnucash/trunk/src/gnc/WeakPointer.hpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -0,0 +1,65 @@
+#ifndef GNC_WEAKPOINTER_HPP
+#define GNC_WEAKPOINTER_HPP
+
+namespace gnc
+{
+
+/** A thin wrapper for a C object which is owned by someone else.
+ *
+ * This copies the interface of the boost::scoped_ptr, but with the
+ * boost::shared_ptr possiblity of a custom deleter function because
+ * we need that.
+ */
+template<class T>
+class WeakPointer
+{
+public:
+ typedef T element_type;
+private:
+ element_type *m_ptr;
+ typedef WeakPointer<T> this_type;
+public:
+
+ WeakPointer(element_type* ptr = 0)
+ : m_ptr(ptr)
+ { }
+
+ void reset(element_type* ptr = 0)
+ {
+ m_ptr = ptr;
+ }
+
+ T & operator*() const // never throws
+ {
+ assert(m_ptr != 0);
+ return *m_ptr;
+ }
+
+ T * operator->() const // never throws
+ {
+ assert(m_ptr != 0);
+ return m_ptr;
+ }
+
+ T * get() const // never throws
+ {
+ return m_ptr;
+ }
+
+ // implicit conversion to "bool"
+ typedef T * this_type::*unspecified_bool_type;
+ operator unspecified_bool_type() const // never throws
+ {
+ return m_ptr == 0? 0: &this_type::m_ptr;
+ }
+
+ bool operator! () const // never throws
+ {
+ return m_ptr == 0;
+ }
+
+};
+
+} // END namespace gnc
+
+#endif
Modified: gnucash/trunk/src/gnc/mainwindow.cpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-03 20:47:10 UTC (rev 18800)
+++ gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -1,23 +1,38 @@
-#include <QtGui>
+#include <QtGui/QToolBar>
+#include <QtGui/QMessageBox>
+#include <QtGui/QFileDialog>
+#include <QtCore/QSettings>
+#include "config.h"
#include "mainwindow.hpp"
#include "ui_mainwindow.h"
// gnucash includes
-#include "config.h"
-extern "C" {
+extern "C"
+{
#include <glib/gi18n.h>
#include "qof.h"
-#include "engine/gnc-session.h"
#include "engine/gnc-hooks.h"
#include "engine/gnc-filepath-utils.h"
#include "engine/Account.h"
#include "engine/TransLog.h"
}
+#include "gnc/Account.hpp"
+#include "gnc/Book.hpp"
+
namespace gnc
{
+inline QString errorToString(QofBackendError err)
+{
+ return QString::fromStdString(errorToStringPair(err).first);
+}
+inline QString errorToDescription(QofBackendError err)
+{
+ return QString::fromStdString(errorToStringPair(err).second);
+}
+
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
@@ -37,7 +52,7 @@
setWindowIcon(QIcon(":/pixmaps/gnucash-icon-32x32.png"));
- setCurrentFile("");
+ newFile();
setUnifiedTitleAndToolBarOnMac(true);
}
@@ -45,33 +60,6 @@
{
}
-void MainWindow::closeEvent(QCloseEvent *event)
-{
- if (maybeSave())
- {
- writeSettings();
- event->accept();
-
- QofSession *session = gnc_get_current_session ();
-
- /* disable events; otherwise the mass deletion of accounts and
- * transactions during shutdown would cause massive redraws */
- qof_event_suspend ();
-
- qof_session_call_close_hooks(session);
- gnc_hook_run(HOOK_BOOK_CLOSED, session);
- gnc_clear_current_session();
-
- gnc_get_current_session ();
-
- qof_event_resume ();
- }
- else
- {
- event->ignore();
- }
-}
-
void MainWindow::open()
{
if (maybeSave())
@@ -196,12 +184,56 @@
return true;
}
+void MainWindow::setCurrentFile(const QString &fileName)
+{
+ curFile = fileName;
+ ui->textEdit->document()->setModified(false);
+ setWindowModified(false);
+
+ QString shownName;
+ if (curFile.isEmpty())
+ shownName = "untitled.txt";
+ else
+ shownName = strippedName(curFile);
+
+ setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Application")));
+}
+
+QString MainWindow::strippedName(const QString &fullFileName)
+{
+ return QFileInfo(fullFileName).fileName();
+}
+
// ////////////////////////////////////////////////////////////
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ if (maybeSave())
+ {
+ writeSettings();
+ event->accept();
+
+ /* disable events; otherwise the mass deletion of accounts and
+ * transactions during shutdown would cause massive redraws */
+ qof_event_suspend ();
+
+ qof_session_call_close_hooks(m_session.get());
+ gnc_hook_run(HOOK_BOOK_CLOSED, m_session.get());
+
+ m_session.reset();
+
+ qof_event_resume ();
+ }
+ else
+ {
+ event->ignore();
+ }
+}
+
static void
-gnc_book_opened (void)
+gnc_book_opened (Session& sess)
{
- gnc_hook_run(HOOK_BOOK_OPENED, gnc_get_current_session());
+ gnc_hook_run(HOOK_BOOK_OPENED, sess.get());
}
void MainWindow::newFile()
@@ -209,30 +241,29 @@
if (maybeSave())
{
- if (gnc_current_session_exist()) {
- QofSession *session = gnc_get_current_session ();
+ if (m_session.get())
+ {
+ /* close any ongoing file sessions, and free the accounts.
+ * disable events so we don't get spammed by redraws. */
+ qof_event_suspend ();
- /* close any ongoing file sessions, and free the accounts.
- * disable events so we don't get spammed by redraws. */
- qof_event_suspend ();
+ m_session.call_close_hooks();
+ gnc_hook_run(HOOK_BOOK_CLOSED, m_session.get());
- qof_session_call_close_hooks(session);
- gnc_hook_run(HOOK_BOOK_CLOSED, session);
+ m_session.reset();
+ qof_event_resume ();
+ }
- gnc_clear_current_session();
- qof_event_resume ();
- }
+ /* start a new book */
+ m_session.reset(Session::newInstance());
- /* start a new book */
- gnc_get_current_session ();
+ gnc_hook_run(HOOK_NEW_BOOK, NULL);
- gnc_hook_run(HOOK_NEW_BOOK, NULL);
+ //gnc_gui_refresh_all ();
- //gnc_gui_refresh_all ();
+ /* Call this after re-enabling events. */
+ gnc_book_opened (m_session);
- /* Call this after re-enabling events. */
- gnc_book_opened ();
-
setCurrentFile("");
}
}
@@ -240,7 +271,7 @@
void MainWindow::loadFile(const QString &fileName)
{
if (fileName.isEmpty())
- return;
+ return;
// copied from gnc_post_file_open, gnome-utils/gnc-file.c
@@ -254,58 +285,57 @@
/* -------------- BEGIN CORE SESSION CODE ------------- */
/* -- this code is almost identical in FileOpen and FileSaveAs -- */
- QofSession *current_session = gnc_get_current_session();
- qof_session_call_close_hooks(current_session);
- gnc_hook_run(HOOK_BOOK_CLOSED, current_session);
- gnc_clear_current_session();
+ m_session.call_close_hooks();
+ gnc_hook_run(HOOK_BOOK_CLOSED, m_session.get());
+ m_session.reset();
/* load the accounts from the users datafile */
/* but first, check to make sure we've got a session going. */
QofSession *new_session = qof_session_new ();
- bool uh_oh = false;
+ bool we_are_in_error = false;
QByteArray newfile = fileName.toUtf8();
qof_session_begin (new_session, newfile, FALSE, FALSE);
QofBackendError io_err = qof_session_get_error (new_session);
/* if file appears to be locked, ask the user ... */
if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
{
- QString fmt1 = tr("GnuCash could not obtain the lock for %1.").arg(fileName);
- QString fmt2 =
- ((ERR_BACKEND_LOCKED == io_err)
- ? tr("That database may be in use by another user, "
- "in which case you should not open the database. "
- "What would you like to do? Open anyway? FIXME")
- : tr("That database may be on a read-only file system, "
- "or you may not have write permission for the directory. "
- "If you proceed you may not be able to save any changes. "
- "What would you like to do? Open anyway? FIXME"));
+ QString fmt1 = tr("GnuCash could not obtain the lock for %1.").arg(fileName);
+ QString fmt2 =
+ ((ERR_BACKEND_LOCKED == io_err)
+ ? tr("That database may be in use by another user, "
+ "in which case you should not open the database. "
+ "What would you like to do? Open anyway? FIXME")
+ : tr("That database may be on a read-only file system, "
+ "or you may not have write permission for the directory. "
+ "If you proceed you may not be able to save any changes. "
+ "What would you like to do? Open anyway? FIXME"));
if (QMessageBox::question(this, fmt1, fmt2)
- == QMessageBox::Ok)
- {
- /* user told us to ignore locks. So ignore them. */
- qof_session_begin (new_session, newfile, TRUE, FALSE);
- }
- else
- {
- /* Can't use the given file, so just create a new
- * database so that the user will get a window that
- * they can click "Exit" on.
- */
- newFile();
- }
+ == QMessageBox::Ok)
+ {
+ /* user told us to ignore locks. So ignore them. */
+ qof_session_begin (new_session, newfile, TRUE, FALSE);
+ }
+ else
+ {
+ /* Can't use the given file, so just create a new
+ * database so that the user will get a window that
+ * they can click "Exit" on.
+ */
+ newFile();
+ }
}
/* if the database doesn't exist, ask the user ... */
else if ((ERR_BACKEND_NO_SUCH_DB == io_err) ||
- (ERR_SQL_DB_TOO_OLD == io_err))
+ (ERR_SQL_DB_TOO_OLD == io_err))
{
if (QMessageBox::question(this, tr("Create New File?"),
- tr("The file %1 does not exist. Do you want to create it?").arg(fileName))
- == QMessageBox::Ok)
- {
- /* user told us to create a new database. Do it. */
- qof_session_begin (new_session, newfile, FALSE, TRUE);
- }
+ tr("The file %1 does not exist. Do you want to create it?").arg(fileName))
+ == QMessageBox::Ok)
+ {
+ /* user told us to create a new database. Do it. */
+ qof_session_begin (new_session, newfile, FALSE, TRUE);
+ }
}
QApplication::setOverrideCursor(Qt::WaitCursor);
@@ -314,52 +344,63 @@
* don't bother with the message, just die. */
io_err = qof_session_get_error (new_session);
if ((ERR_BACKEND_LOCKED == io_err) ||
- (ERR_BACKEND_READONLY == io_err) ||
- (ERR_BACKEND_NO_SUCH_DB == io_err) ||
- (ERR_SQL_DB_TOO_OLD == io_err))
+ (ERR_BACKEND_READONLY == io_err) ||
+ (ERR_BACKEND_NO_SUCH_DB == io_err) ||
+ (ERR_SQL_DB_TOO_OLD == io_err))
{
- uh_oh = true;
+ we_are_in_error = true;
}
else
{
- uh_oh = !(QMessageBox::question(this, tr("Open anyway?"),
- tr("The file %1 has some errors (FIXME). Open anyway?").arg(fileName))
- == QMessageBox::Ok);
+ if (io_err != ERR_BACKEND_NO_ERR)
+ {
+ we_are_in_error = !(QMessageBox::question(this, tr("Open anyway?"),
+ tr("The file %1 has some errors: %2: %3. Open anyway?")
+ .arg(fileName)
+ .arg(errorToString(io_err))
+ .arg(errorToDescription(io_err)))
+ == QMessageBox::Ok);
+ }
}
- if (!uh_oh)
+ if (!we_are_in_error)
{
- ::Account *new_root;
+ char * logpath = xaccResolveFilePath(newfile);
+ PINFO ("logpath=%s", logpath ? logpath : "(null)");
+ xaccLogSetBaseName (logpath);
+ xaccLogDisable();
- char * logpath = xaccResolveFilePath(newfile);
- PINFO ("logpath=%s", logpath ? logpath : "(null)");
- xaccLogSetBaseName (logpath);
- xaccLogDisable();
+ statusBar()->showMessage(tr("Loading user data..."), 2000);
+ qof_session_load (new_session, NULL);
+ xaccLogEnable();
- statusBar()->showMessage(tr("Loading user data..."), 2000);
- qof_session_load (new_session, NULL);
- xaccLogEnable();
+ /* check for i/o error, put up appropriate error dialog */
+ io_err = qof_session_get_error (new_session);
- /* check for i/o error, put up appropriate error dialog */
- io_err = qof_session_get_error (new_session);
-
- uh_oh = !(QMessageBox::question(this, tr("Error on Open"),
- tr("There was an error opening the file %1. FIXME").arg(fileName))
- == QMessageBox::Ok);
-
- new_root = gnc_book_get_root_account (qof_session_get_book (new_session));
- if (uh_oh) new_root = NULL;
+ if (io_err != ERR_BACKEND_NO_ERR)
+ {
+ we_are_in_error = !(QMessageBox::question(this, tr("Error on Open"),
+ tr("There was an error opening the file %1: %2: %3. FIXME")
+ .arg(fileName)
+ .arg(errorToString(io_err))
+ .arg(errorToDescription(io_err)))
+ == QMessageBox::Ok);
+ }
}
/* if we got to here, then we've successfully gotten a new session */
/* close up the old file session (if any) */
- gnc_set_current_session(new_session);
+ m_session.reset(new_session);
+ ::Account * new_root = m_session.get_book().get_root_account().get();
+ if (we_are_in_error)
+ new_root = NULL;
+
qof_event_resume ();
/* Call this after re-enabling events. */
- gnc_book_opened ();
+ gnc_book_opened (m_session);
QApplication::restoreOverrideCursor();
@@ -381,7 +422,7 @@
file.close();
QApplication::setOverrideCursor(Qt::WaitCursor);
- QofSession *session = gnc_get_current_session ();
+ QofSession *session = m_session.get();
/* Make sure all of the data from the old file is loaded */
qof_session_ensure_all_data_loaded(session);
@@ -398,25 +439,25 @@
if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
{
if (QMessageBox::question(this, tr("Ignore Lock?"),
- tr("The file %1 is locked. Should we ignore the lock?").arg(fileName))
- == QMessageBox::Ok)
- {
- /* user told us to ignore locks. So ignore them. */
- qof_session_begin (new_session, newfile, TRUE, FALSE);
- }
+ tr("The file %1 is locked. Should we ignore the lock?").arg(fileName))
+ == QMessageBox::Ok)
+ {
+ /* user told us to ignore locks. So ignore them. */
+ qof_session_begin (new_session, newfile, TRUE, FALSE);
+ }
}
/* if the database doesn't exist, ask the user ... */
else if ((ERR_FILEIO_FILE_NOT_FOUND == io_err) ||
- (ERR_BACKEND_NO_SUCH_DB == io_err) ||
- (ERR_SQL_DB_TOO_OLD == io_err))
+ (ERR_BACKEND_NO_SUCH_DB == io_err) ||
+ (ERR_SQL_DB_TOO_OLD == io_err))
{
- if (QMessageBox::question(this, tr("Create New File?"),
- tr("The file %1 does not exist. Should it be created?").arg(fileName)))
- {
- /* user told us to create a new database. Do it. */
- qof_session_begin (new_session, newfile, FALSE, TRUE);
- }
+ if (QMessageBox::question(this, tr("Create New File?"),
+ tr("The file %1 does not exist. Should it be created?").arg(fileName)))
+ {
+ /* user told us to create a new database. Do it. */
+ qof_session_begin (new_session, newfile, FALSE, TRUE);
+ }
}
/* check again for session errors (since above dialog may have
@@ -426,12 +467,15 @@
io_err = qof_session_get_error (new_session);
if (ERR_BACKEND_NO_ERR != io_err)
{
- QMessageBox::critical(this, tr("Still in Error"),
- tr("The file %1 still cannot be written. FIXME").arg(fileName));
- xaccLogDisable();
- qof_session_destroy (new_session);
- xaccLogEnable();
- return false;
+ QMessageBox::critical(this, tr("Still in Error"),
+ tr("The file %1 still cannot be written: %2: %3. FIXME")
+ .arg(fileName)
+ .arg(errorToString(io_err))
+ .arg(errorToDescription(io_err)));
+ xaccLogDisable();
+ qof_session_destroy (new_session);
+ xaccLogEnable();
+ return false;
}
/* Prevent race condition between swapping the contents of the two
@@ -443,14 +487,14 @@
/* if we got to here, then we've successfully gotten a new session */
/* close up the old file session (if any) */
qof_session_swap_data (session, new_session);
- gnc_clear_current_session();
+ m_session.reset();
session = NULL;
/* XXX At this point, we should really mark the data in the new session
* as being 'dirty', since we haven't saved it at all under the new
* session. But I'm lazy...
*/
- gnc_set_current_session(new_session);
+ m_session.reset(new_session);
qof_event_resume();
@@ -464,24 +508,4 @@
return true;
}
-void MainWindow::setCurrentFile(const QString &fileName)
-{
- curFile = fileName;
- ui->textEdit->document()->setModified(false);
- setWindowModified(false);
-
- QString shownName;
- if (curFile.isEmpty())
- shownName = "untitled.txt";
- else
- shownName = strippedName(curFile);
-
- setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Application")));
-}
-
-QString MainWindow::strippedName(const QString &fullFileName)
-{
- return QFileInfo(fullFileName).fileName();
-}
-
} // END namespace gnc
Modified: gnucash/trunk/src/gnc/mainwindow.hpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.hpp 2010-03-03 20:47:10 UTC (rev 18800)
+++ gnucash/trunk/src/gnc/mainwindow.hpp 2010-03-03 20:47:31 UTC (rev 18801)
@@ -3,6 +3,7 @@
#include <QMainWindow>
#include <QSharedPointer>
+#include "gnc/Session.hpp"
class QAction;
class QMenu;
@@ -55,6 +56,8 @@
QToolBar *fileToolBar;
QToolBar *editToolBar;
+
+ Session m_session;
};
} // END namespace gnc
More information about the gnucash-changes
mailing list