r18782 - gnucash/trunk/src/gnc - More C++/Qt4 frontend work.

Christian Stimming cstim at code.gnucash.org
Tue Mar 2 15:22:23 EST 2010


Author: cstim
Date: 2010-03-02 15:22:23 -0500 (Tue, 02 Mar 2010)
New Revision: 18782
Trac: http://svn.gnucash.org/trac/changeset/18782

Modified:
   gnucash/trunk/src/gnc/main.cpp
   gnucash/trunk/src/gnc/mainwindow.cpp
Log:
More C++/Qt4 frontend work.

Modified: gnucash/trunk/src/gnc/main.cpp
===================================================================
--- gnucash/trunk/src/gnc/main.cpp	2010-03-02 20:22:01 UTC (rev 18781)
+++ gnucash/trunk/src/gnc/main.cpp	2010-03-02 20:22:23 UTC (rev 18782)
@@ -41,6 +41,7 @@
 #include "core-utils/gnc-main.h"
 #include "engine/gnc-session.h"
 #include "engine/engine-helpers.h"
+#include "engine/cashobjects.h"
 #include "swig-runtime.h"
 
 #include "gnc-backend-xml.h"
@@ -169,14 +170,20 @@
 
     gnc::gnc_log_init();
 
+    qof_init();
     gnc_module_system_init();
+    cashobjects_register();
 
+    // For the XML file backend
     qof_backend_module_init();
 
     // From here on the new C++ code
     QApplication app(argc, argv);
     gnc::MainWindow mainWin;
     mainWin.show();
-    return app.exec();
 
+    int r = app.exec();
+    qof_close();
+    return r;
+
 }

Modified: gnucash/trunk/src/gnc/mainwindow.cpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.cpp	2010-03-02 20:22:01 UTC (rev 18781)
+++ gnucash/trunk/src/gnc/mainwindow.cpp	2010-03-02 20:22:23 UTC (rev 18782)
@@ -3,9 +3,24 @@
 #include "mainwindow.hpp"
 #include "ui_mainwindow.h"
 
+// gnucash includes
+#include "config.h"
+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"
+}
+
 namespace gnc
 {
 
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_GUI;
+
 MainWindow::MainWindow()
         : ui(new Ui::MainWindow)
 {
@@ -36,6 +51,20 @@
     {
         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
     {
@@ -43,15 +72,6 @@
     }
 }
 
-void MainWindow::newFile()
-{
-    if (maybeSave())
-    {
-        ui->textEdit->clear();
-        setCurrentFile("");
-    }
-}
-
 void MainWindow::open()
 {
     if (maybeSave())
@@ -176,21 +196,171 @@
     return true;
 }
 
+// ////////////////////////////////////////////////////////////
+
+static void
+gnc_book_opened (void)
+{
+    gnc_hook_run(HOOK_BOOK_OPENED, gnc_get_current_session());
+}
+
+void MainWindow::newFile()
+{
+    if (maybeSave())
+    {
+
+	if (gnc_current_session_exist()) {
+	    QofSession *session = gnc_get_current_session ();
+
+	    /* close any ongoing file sessions, and free the accounts.
+	     * disable events so we don't get spammed by redraws. */
+	    qof_event_suspend ();
+
+	    qof_session_call_close_hooks(session);
+	    gnc_hook_run(HOOK_BOOK_CLOSED, session);
+
+	    gnc_clear_current_session();
+	    qof_event_resume ();
+	}
+
+	/* start a new book */
+	gnc_get_current_session ();
+
+	gnc_hook_run(HOOK_NEW_BOOK, NULL);
+
+	//gnc_gui_refresh_all ();
+
+	/* Call this after re-enabling events. */
+	gnc_book_opened ();
+
+        setCurrentFile("");
+    }
+}
+
 void MainWindow::loadFile(const QString &fileName)
 {
-    QFile file(fileName);
-    if (!file.open(QFile::ReadOnly | QFile::Text))
+    if (fileName.isEmpty())
+	return;
+
+    // copied from gnc_post_file_open, gnome-utils/gnc-file.c
+
+    /* disable events while moving over to the new set of accounts;
+     * the mass deletion of accounts and transactions during
+     * switchover would otherwise cause excessive redraws. */
+    qof_event_suspend ();
+
+    /* Change the mouse to a busy cursor */
+    //gnc_set_busy_cursor (NULL, TRUE);
+
+    /* -------------- 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();
+
+    /* 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;
+    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)
     {
-        QMessageBox::warning(this, tr("Application"),
-                             tr("Cannot read file %1:\n%2.")
-                             .arg(fileName)
-                             .arg(file.errorString()));
-        return;
+	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();
+	}
     }
+    /* 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))
+    {
+        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);
+	}
+    }
 
-    QTextStream in(&file);
     QApplication::setOverrideCursor(Qt::WaitCursor);
-    ui->textEdit->setPlainText(in.readAll());
+    /* Check for errors again, since above may have cleared the lock.
+     * If its still locked, still, doesn't exist, still too old, then
+     * 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))
+    {
+	uh_oh = 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 (!uh_oh)
+    {
+	::Account *new_root;
+
+	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();
+
+	/* 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 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);
+
+    qof_event_resume ();
+
+    /* Call this after re-enabling events. */
+    gnc_book_opened ();
+
     QApplication::restoreOverrideCursor();
 
     setCurrentFile(fileName);
@@ -200,7 +370,7 @@
 bool MainWindow::saveFile(const QString &fileName)
 {
     QFile file(fileName);
-    if (!file.open(QFile::WriteOnly | QFile::Text))
+    if (!file.open(QFile::WriteOnly))
     {
         QMessageBox::warning(this, tr("Application"),
                              tr("Cannot write file %1:\n%2.")
@@ -208,10 +378,85 @@
                              .arg(file.errorString()));
         return false;
     }
+    file.close();
+    QApplication::setOverrideCursor(Qt::WaitCursor);
 
-    QTextStream out(&file);
-    QApplication::setOverrideCursor(Qt::WaitCursor);
-    out << ui->textEdit->toPlainText();
+    QofSession *session = gnc_get_current_session ();
+    /* Make sure all of the data from the old file is loaded */
+    qof_session_ensure_all_data_loaded(session);
+
+    /* -- this session code is NOT identical in FileOpen and FileSaveAs -- */
+
+    QByteArray newfile = fileName.toUtf8();
+    xaccLogSetBaseName(newfile); //FIXME: This is premature.
+    QofSession *new_session = qof_session_new ();
+    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)
+    {
+        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);
+	}
+    }
+
+    /* 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))
+    {
+	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
+     * cleared a file lock & moved things forward some more)
+     * This time, errors will be fatal.
+     */
+    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;
+    }
+
+    /* Prevent race condition between swapping the contents of the two
+     * sessions, and actually installing the new session as the current
+     * one. Any event callbacks that occur in this interval will have
+     * problems if they check for the current book. */
+    qof_event_suspend();
+
+    /* 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();
+    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);
+
+    qof_event_resume();
+
+    /* --------------- END CORE SESSION CODE -------------- */
+
+
     QApplication::restoreOverrideCursor();
 
     setCurrentFile(fileName);



More information about the gnucash-changes mailing list