mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Cutecash: Fix file loading, saving, and save-as. Works fine now.
Also, use the new GDate setter/getter for the transaction time. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18926 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
59be2dc692
commit
4e3be7b89c
@ -126,9 +126,6 @@ IF (UNIX)
|
||||
")
|
||||
ENDIF (UNIX)
|
||||
|
||||
# Let cmake copy the created file only on changes.
|
||||
#CONFIGURE_FILE (${CONFIG_H} ${CMAKE_CURRENT_BINARY_DIR}/config.h COPYONLY)
|
||||
|
||||
# ############################################################
|
||||
|
||||
# The subdirectories
|
||||
|
@ -35,15 +35,13 @@ SET (libgnc_core_utils_SOURCES
|
||||
SET_SOURCE_FILES_PROPERTIES (${libgnc_core_utils_SOURCES} PROPERTIES OBJECT_DEPENDS ${CONFIG_H})
|
||||
|
||||
# Workaround to create a very simple gncla-dir.h file
|
||||
FILE (WRITE ${CMAKE_CURRENT_BINARY_DIR}/gncla-dir.h.tmp "
|
||||
FILE (WRITE ${CMAKE_CURRENT_BINARY_DIR}/gncla-dir.h "
|
||||
#define PREFIX \"${CMAKE_INSTALL_PREFIX}\"
|
||||
#define DATADIR \"${CMAKE_INSTALL_PREFIX}/share\"
|
||||
#define SYSCONFDIR \"${CMAKE_INSTALL_PREFIX}/etc\"
|
||||
#define LIBDIR \"${CMAKE_INSTALL_PREFIX}/lib\"
|
||||
#define LOCALE_DATADIRNAME \"share\"
|
||||
")
|
||||
# Let cmake copy the created file only on changes.
|
||||
CONFIGURE_FILE (${CMAKE_CURRENT_BINARY_DIR}/gncla-dir.h.tmp ${CMAKE_CURRENT_BINARY_DIR}/gncla-dir.h COPYONLY)
|
||||
|
||||
SET (libgnc_core_utils_HEADERS
|
||||
binreloc.h
|
||||
|
@ -21,6 +21,7 @@ SET (gnc_SOURCES
|
||||
SplitListModel.cpp
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow-file.cpp
|
||||
)
|
||||
|
||||
SET (gnc_QOBJECT_HEADERS
|
||||
|
@ -175,7 +175,7 @@ QUndoCommand* setTransactionDate(Transaction& t, const QDate& newValue)
|
||||
{
|
||||
return new Cmd<Transaction, QDate>(QObject::tr("Edit Transaction Date"),
|
||||
t, &Transaction::setDatePosted,
|
||||
t.getDatePosted().date(), newValue);
|
||||
t.getDatePosted(), newValue);
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,6 +63,13 @@ inline QDateTime toQDateTime(const ::Timespec& timespec)
|
||||
result.setTimeSpec(Qt::UTC);
|
||||
return result;
|
||||
}
|
||||
inline QDate toQDate(const ::GDate& d)
|
||||
{
|
||||
if (g_date_valid(&d))
|
||||
return QDate(g_date_year(&d), g_date_month(&d), g_date_day(&d));
|
||||
else
|
||||
return QDate();
|
||||
}
|
||||
inline ::Timespec toTimespec(const QDateTime& qdt)
|
||||
{
|
||||
::Timespec result;
|
||||
|
@ -122,7 +122,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
return trans.getDatePosted().date();
|
||||
return trans.getDatePosted();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@ -307,7 +307,7 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in
|
||||
Transaction trans = split.getParent();
|
||||
Split other = split.getOtherSplit();
|
||||
Q_ASSERT(other);
|
||||
Commodity originCommodity =split.getAccount().getCommodity();
|
||||
Commodity originCommodity = split.getAccount().getCommodity();
|
||||
Commodity transCommodity = trans.getCurrency();
|
||||
Commodity otherCommodity = other.getAccount().getCommodity();
|
||||
if (originCommodity != transCommodity
|
||||
|
@ -87,10 +87,9 @@ public:
|
||||
bool isBalanced() const { return xaccTransIsBalanced(get()); }
|
||||
Numeric getAccountConvRate(const Account& acc) const { return xaccTransGetAccountConvRate(get(), acc.get()); }
|
||||
|
||||
void setDatePosted(const QDate& t) { xaccTransSetDatePostedSecs(get(), QDateTime(t, QTime(12,0,0)).toTime_t()); }
|
||||
void setDatePosted(const QDateTime& t) { xaccTransSetDatePostedSecs(get(), t.toTime_t()); }
|
||||
void setDatePosted(const QDate& d) { xaccTransSetDate(get(), d.day(), d.month(), d.year()); }
|
||||
void setDateEntered(const QDateTime& t) { xaccTransSetDateEnteredSecs(get(), t.toTime_t()); }
|
||||
QDateTime getDatePosted() const { return toQDateTime(xaccTransRetDatePostedTS(get())); }
|
||||
QDate getDatePosted() const { return toQDate(xaccTransGetDatePostedGDate(get())); }
|
||||
QDateTime getDateEntered() const { return toQDateTime(xaccTransRetDateEnteredTS(get())); }
|
||||
|
||||
};
|
||||
|
774
src/gnc/mainwindow-file.cpp
Normal file
774
src/gnc/mainwindow-file.cpp
Normal file
@ -0,0 +1,774 @@
|
||||
/*
|
||||
* mainwindow-file.cpp
|
||||
* Copyright (C) 2010 Christian Stimming
|
||||
*
|
||||
* 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, contact:
|
||||
*
|
||||
* Free Software Foundation Voice: +1-617-542-5942
|
||||
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
|
||||
* Boston, MA 02110-1301, USA gnu@gnu.org
|
||||
*/
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QCloseEvent>
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QProgressBar>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QToolBar>
|
||||
#include <QtGui/QUndoStack>
|
||||
#include <QDebug>
|
||||
|
||||
#include "config.h"
|
||||
#include "mainwindow.hpp"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
// gnucash includes
|
||||
#include <glib/gi18n.h>
|
||||
extern "C"
|
||||
{
|
||||
#include "qof.h"
|
||||
#include "engine/gnc-hooks.h"
|
||||
#include "core-utils/gnc-uri-utils.h"
|
||||
#include "engine/Account.h"
|
||||
#include "engine/TransLog.h"
|
||||
}
|
||||
|
||||
#include "gnc/Account.hpp"
|
||||
#include "gnc/AccountItemModel.hpp"
|
||||
#include "gnc/Book.hpp"
|
||||
#include "gnc/Numeric.hpp"
|
||||
#include "gnc/Split.hpp"
|
||||
#include "gnc/SplitListModel.hpp"
|
||||
#include "gnc/RecentFileMenu.hpp"
|
||||
|
||||
#include "gnc/Cmd.hpp"
|
||||
|
||||
namespace gnc
|
||||
{
|
||||
|
||||
inline QString errorToString(QofBackendError err)
|
||||
{
|
||||
return errorToStringPair(err).first;
|
||||
}
|
||||
inline QString errorToDescription(QofBackendError err)
|
||||
{
|
||||
return errorToStringPair(err).second;
|
||||
}
|
||||
|
||||
/* This static indicates the debugging module that this .o belongs to. */
|
||||
static QofLogModule log_module = GNC_MOD_GUI;
|
||||
static const char* PROPERTY_TAB_PREVIOUSPOS = "tab_previouspos";
|
||||
static gint save_in_progress = 0;
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
bool MainWindow::show_session_error (QWidget *parent,
|
||||
::QofBackendError io_error,
|
||||
const QString& filename,
|
||||
GNCFileDialogType type)
|
||||
{
|
||||
bool should_abort = true;
|
||||
QString fmt;
|
||||
|
||||
switch (io_error)
|
||||
{
|
||||
case ERR_BACKEND_NO_ERR:
|
||||
should_abort = FALSE;
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_NO_HANDLER:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("No suitable backend was found for %1.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_NO_BACKEND:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The URL %1 is not supported by this version of GnuCash.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_BAD_URL:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("Can't parse the URL %1.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_CANT_CONNECT:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("Can't connect to %1. "
|
||||
"The host, username or password were incorrect.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_CONN_LOST:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("Can't connect to %1. "
|
||||
"Connection was lost, unable to send data.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_TOO_NEW:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("This file/URL appears to be from a newer version "
|
||||
"of GnuCash. You must upgrade your version of GnuCash "
|
||||
"to work with this data."));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_NO_SUCH_DB:
|
||||
if (QMessageBox::question(parent, tr("Create New File?"),
|
||||
tr("The database %1 doesn't seem to exist. "
|
||||
"Do you want to create it?").arg(filename),
|
||||
QMessageBox::Ok | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok)
|
||||
{
|
||||
should_abort = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_LOCKED:
|
||||
switch (type)
|
||||
{
|
||||
case GNC_FILE_DIALOG_OPEN:
|
||||
default:
|
||||
fmt = tr("GnuCash could not obtain the lock for %1. "
|
||||
"That database may be in use by another user, "
|
||||
"in which case you should not open the database. "
|
||||
"Do you want to proceed with opening the database?");
|
||||
break;
|
||||
|
||||
case GNC_FILE_DIALOG_IMPORT:
|
||||
fmt = tr("GnuCash could not obtain the lock for %1. "
|
||||
"That database may be in use by another user, "
|
||||
"in which case you should not import the database. "
|
||||
"Do you want to proceed with importing the database?");
|
||||
break;
|
||||
|
||||
case GNC_FILE_DIALOG_SAVE:
|
||||
fmt = tr("GnuCash could not obtain the lock for %1. "
|
||||
"That database may be in use by another user, "
|
||||
"in which case you should not save the database. "
|
||||
"Do you want to proceed with saving the database?");
|
||||
break;
|
||||
|
||||
case GNC_FILE_DIALOG_EXPORT:
|
||||
fmt = tr("GnuCash could not obtain the lock for %1. "
|
||||
"That database may be in use by another user, "
|
||||
"in which case you should not export the database. "
|
||||
"Do you want to proceed with exporting the database?");
|
||||
break;
|
||||
}
|
||||
|
||||
if (QMessageBox::question(parent, tr("Create New File?"),
|
||||
tr("The database %1 doesn't seem to exist. "
|
||||
"Do you want to create it?").arg(filename),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
|
||||
== QMessageBox::Yes)
|
||||
{
|
||||
should_abort = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_READONLY:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("GnuCash could not write to %1. "
|
||||
"That database may be on a read-only file system, "
|
||||
"or you may not have write permission for the directory.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_DATA_CORRUPT:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The file/URL %1 "
|
||||
"does not contain GnuCash data or the data is corrupt.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_SERVER_ERR:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The server at URL %1 "
|
||||
"experienced an error or encountered bad or corrupt data.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_PERM:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("You do not have permission to access %1.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_BACKEND_MISC:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("An error occurred while processing %1.").arg(filename));
|
||||
break;
|
||||
|
||||
|
||||
case ERR_FILEIO_FILE_BAD_READ:
|
||||
if (QMessageBox::question(parent, tr("Continue?"),
|
||||
tr("There was an error reading the file. "
|
||||
"Do you want to continue?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok)
|
||||
{
|
||||
should_abort = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_PARSE_ERROR:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("There was an error parsing the file %1.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_FILE_EMPTY:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The file %1 is empty.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_FILE_NOT_FOUND:
|
||||
if (type == GNC_FILE_DIALOG_SAVE)
|
||||
{
|
||||
should_abort = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The file %1 could not be found.").arg(filename));
|
||||
}
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_FILE_TOO_OLD:
|
||||
if (QMessageBox::question(parent, tr("Continue?"),
|
||||
tr("This file is from an older version of GnuCash. "
|
||||
"Do you want to continue?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok)
|
||||
{
|
||||
should_abort = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_UNKNOWN_FILE_TYPE:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The file type of file %1 is unknown.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_BACKUP_ERROR:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("Could not make a backup of the file %1").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_WRITE_ERROR:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("Could not write to file %1. Check that you have "
|
||||
"permission to write to this file and that "
|
||||
"there is sufficient space to create it.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_FILE_EACCES:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("No read permission to read from file %1.").arg(filename));
|
||||
break;
|
||||
|
||||
case ERR_SQL_DB_TOO_OLD:
|
||||
if (QMessageBox::question(parent, tr("Upgrade Database?"),
|
||||
tr("This database is from an older version of GnuCash. "
|
||||
"Do you want to want to upgrade the database "
|
||||
"to the current version?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
|
||||
== QMessageBox::Yes)
|
||||
{
|
||||
should_abort = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ERR_SQL_DB_BUSY:
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("The SQL database is in use by other users, "
|
||||
"and the upgrade cannot be performed until they logoff. "
|
||||
"If there are currently no other users, consult the "
|
||||
"documentation to learn how to clear out dangling login "
|
||||
"sessions."));
|
||||
break;
|
||||
|
||||
default:
|
||||
PERR("FIXME: Unhandled error %d", io_error);
|
||||
QMessageBox::critical(parent, tr("Error"),
|
||||
tr("An unknown I/O error (%1) occurred.").arg(int(io_error)));
|
||||
break;
|
||||
}
|
||||
|
||||
return should_abort;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void
|
||||
gnc_book_opened (Session& sess)
|
||||
{
|
||||
gnc_hook_run(HOOK_BOOK_OPENED, sess.get());
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
/** This is a workaround function object so that we can obtain a
|
||||
* QofPercentageFunc without extra boost::bind usage; obviously due to
|
||||
* the static member variable it will not work if multiple instances
|
||||
* are in use simultaneously */
|
||||
class progress_functor
|
||||
{
|
||||
public:
|
||||
progress_functor(QProgressBar *progressBar)
|
||||
{
|
||||
m_progressBar = progressBar;
|
||||
}
|
||||
~progress_functor()
|
||||
{
|
||||
m_progressBar = NULL;
|
||||
}
|
||||
static void static_func(const char *message, double percent)
|
||||
{
|
||||
assert(m_progressBar);
|
||||
m_progressBar->setValue(int(percent));
|
||||
// Give the Qt event loop some time
|
||||
qApp->processEvents();
|
||||
}
|
||||
private:
|
||||
static QProgressBar *m_progressBar;
|
||||
};
|
||||
QProgressBar *progress_functor::m_progressBar = NULL;
|
||||
|
||||
} // END namespace anonymous
|
||||
|
||||
|
||||
void MainWindow::loadFile(const QString &fileName)
|
||||
{
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
// copied from gnc_post_file_open, gnome-utils/gnc-file.c
|
||||
|
||||
QString newfile_qstring =
|
||||
gchar_to_QString(gnc_uri_normalize_uri(fileName.toUtf8(), TRUE));
|
||||
if (newfile_qstring.isEmpty())
|
||||
{
|
||||
show_session_error (this, ERR_FILEIO_FILE_NOT_FOUND, fileName,
|
||||
GNC_FILE_DIALOG_OPEN);
|
||||
return;
|
||||
}
|
||||
QByteArray newfile = newfile_qstring.toUtf8();
|
||||
|
||||
/* 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 cusor
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
/* -------------- BEGIN CORE SESSION CODE ------------- */
|
||||
/* -- this code is almost identical in FileOpen and FileSaveAs -- */
|
||||
m_session.call_close_hooks();
|
||||
gnc_hook_run(HOOK_BOOK_CLOSED, m_session.get());
|
||||
qof_session_destroy(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 we_are_in_error = false;
|
||||
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?")
|
||||
: 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?"));
|
||||
QMessageBox msgBox;
|
||||
QPushButton *openAnyway = msgBox.addButton(tr("_Open Anyway"), QMessageBox::ActionRole);
|
||||
QPushButton *createNewFile = msgBox.addButton(tr("_Create New File"), QMessageBox::ActionRole);
|
||||
QPushButton *close = msgBox.addButton(QMessageBox::Close);
|
||||
msgBox.exec();
|
||||
if (msgBox.clickedButton() == openAnyway)
|
||||
{
|
||||
/* user told us to ignore locks. So ignore them. */
|
||||
qof_session_begin (new_session, newfile, TRUE, FALSE);
|
||||
}
|
||||
else if (msgBox.clickedButton() == createNewFile)
|
||||
{
|
||||
/* 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();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
qApp->quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ERR_QSF_OPEN_NOT_MERGE == io_err)
|
||||
{
|
||||
we_are_in_error = true;
|
||||
}
|
||||
/* 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 (false == show_session_error (this, io_err, newfile, GNC_FILE_DIALOG_OPEN))
|
||||
{
|
||||
/* user told us to create a new database. Do it. */
|
||||
qof_session_begin (new_session, newfile, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
we_are_in_error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
we_are_in_error = show_session_error (this, io_err, newfile, GNC_FILE_DIALOG_OPEN);
|
||||
}
|
||||
|
||||
if (!we_are_in_error)
|
||||
{
|
||||
gchar *logpath = NULL;
|
||||
if ( gnc_uri_is_file_uri ( newfile ) )
|
||||
logpath = gnc_uri_get_path(newfile);
|
||||
PINFO ("logpath=%s", logpath ? logpath : "(null)");
|
||||
xaccLogSetBaseName (logpath);
|
||||
g_free ( logpath );
|
||||
|
||||
xaccLogDisable();
|
||||
|
||||
{
|
||||
// Set up a progress bar in the statusBar()
|
||||
QProgressBar progressBar;
|
||||
progressBar.setMinimum(0);
|
||||
progressBar.setMaximum(100);
|
||||
statusBar()->showMessage(tr("Loading user data..."));
|
||||
statusBar()->addPermanentWidget(&progressBar);
|
||||
progressBar.show();
|
||||
// This local progress_functor is a workaround on how to
|
||||
// pass the suitable function pointer to session_load -
|
||||
// not very nice because of its static member, but it does
|
||||
// the trick for now.
|
||||
progress_functor functor(&progressBar);
|
||||
|
||||
// Do the loading.
|
||||
qof_session_load (new_session, &progress_functor::static_func);
|
||||
|
||||
// Remove the progress bar again from the status bar.
|
||||
statusBar()->removeWidget(&progressBar);
|
||||
}
|
||||
xaccLogEnable();
|
||||
|
||||
/* check for i/o error, put up appropriate error dialog */
|
||||
io_err = qof_session_get_error (new_session);
|
||||
|
||||
we_are_in_error = show_session_error(this, io_err, newfile, GNC_FILE_DIALOG_OPEN);
|
||||
|
||||
::Account* new_root_account = gnc_book_get_root_account (qof_session_get_book (new_session));
|
||||
if (we_are_in_error) new_root_account = NULL;
|
||||
|
||||
/* Umm, came up empty-handed, but no error:
|
||||
* The backend forgot to set an error. So make one up. */
|
||||
if (!we_are_in_error && !new_root_account)
|
||||
{
|
||||
we_are_in_error = show_session_error (this, ERR_BACKEND_MISC, newfile,
|
||||
GNC_FILE_DIALOG_OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
/* going down -- abandon ship */
|
||||
if (we_are_in_error)
|
||||
{
|
||||
xaccLogDisable();
|
||||
qof_session_destroy (new_session);
|
||||
xaccLogEnable();
|
||||
|
||||
/* well, no matter what, I think it's a good idea to have a root
|
||||
* account around. For example, early in the gnucash startup
|
||||
* sequence, the user opens a file; if this open fails for any
|
||||
* reason, we don't want to leave them high & dry without a root
|
||||
* account, because if the user continues, then bad things will
|
||||
* happen. */
|
||||
new_session = qof_session_new ();
|
||||
m_session.reset(new_session);
|
||||
|
||||
qof_event_resume ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we got to here, then we've successfully gotten a new session */
|
||||
/* close up the old file session (if any) */
|
||||
m_session.reset(new_session);
|
||||
|
||||
qof_event_resume ();
|
||||
|
||||
/* Call this after re-enabling events. */
|
||||
gnc_book_opened (m_session);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// Some display about this file
|
||||
|
||||
Account root (m_session.get_book().get_root_account());
|
||||
if (root)
|
||||
{
|
||||
m_accountListModel = new AccountListModel(root, this);
|
||||
ui->tableView->setModel(m_accountListModel);
|
||||
|
||||
m_accountTreeModel = new AccountTreeModel(root, this);
|
||||
ui->treeView->setModel(m_accountTreeModel);
|
||||
|
||||
ui->treeViewTab->setProperty(PROPERTY_TAB_PREVIOUSPOS, ui->tabWidget->currentIndex());
|
||||
ui->tabWidget->setCurrentWidget(ui->treeViewTab);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ui->labelMain->setText(tr("No root account"));
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
setCurrentFile(fileName);
|
||||
statusBar()->showMessage(tr("File loaded"), 5000);
|
||||
}
|
||||
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
bool MainWindow::saveFileAs(const QString &fileName)
|
||||
{
|
||||
if (gnc_uri_is_file_uri(fileName.toUtf8()))
|
||||
{
|
||||
QFile file(gchar_to_QString(gnc_uri_get_path(fileName.toUtf8())));
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Application"),
|
||||
tr("Cannot write file %1:\n%2.")
|
||||
.arg(fileName)
|
||||
.arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
/* Check to see if the user specified the same file as the current
|
||||
* file. If so, then just do a simple save, instead of a full save as */
|
||||
/* FIXME Check if it is ok to have a password in the uri here */
|
||||
QString newfile_qstring =
|
||||
gchar_to_QString(gnc_uri_normalize_uri ( fileName.toUtf8(), TRUE ));
|
||||
if (newfile_qstring.isEmpty())
|
||||
{
|
||||
show_session_error (this, ERR_FILEIO_FILE_NOT_FOUND, fileName,
|
||||
GNC_FILE_DIALOG_SAVE);
|
||||
return false;
|
||||
}
|
||||
QByteArray newfile = newfile_qstring.toUtf8();
|
||||
|
||||
QofSession *session = m_session.get();
|
||||
if (m_session.get_url() == fileName)
|
||||
{
|
||||
return saveFile();
|
||||
}
|
||||
|
||||
/* 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 -- */
|
||||
|
||||
save_in_progress++;
|
||||
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 (false == show_session_error (this, io_err, newfile, GNC_FILE_DIALOG_SAVE))
|
||||
{
|
||||
/* 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 (false == show_session_error (this, io_err, newfile, GNC_FILE_DIALOG_SAVE))
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
show_session_error (this, io_err, newfile, GNC_FILE_DIALOG_SAVE);
|
||||
xaccLogDisable();
|
||||
qof_session_destroy (new_session);
|
||||
xaccLogEnable();
|
||||
save_in_progress--;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* oops ... file already exists ... ask user what to do... */
|
||||
if (qof_session_save_may_clobber_data (new_session))
|
||||
{
|
||||
if (QMessageBox::question(this, tr("File Exists"),
|
||||
tr("The file %1 already exists. "
|
||||
"Are you sure you want to overwrite it?").arg(fileName),
|
||||
QMessageBox::Yes | QMessageBox::No)
|
||||
!= QMessageBox::Yes)
|
||||
{
|
||||
/* if user says cancel, we should break out */
|
||||
xaccLogDisable();
|
||||
qof_session_destroy (new_session);
|
||||
xaccLogEnable();
|
||||
save_in_progress--;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Whoa-ok. Blow away the previous file. */
|
||||
}
|
||||
|
||||
/* XXX Would logging make sense for databases as well (mysql/postgres) ?
|
||||
* Currently the logpath is relative to the data file path.
|
||||
* Databases don't have a file path, so no logging will be
|
||||
* done for them in the current setup.
|
||||
*/
|
||||
gchar *logpath = NULL;
|
||||
if ( gnc_uri_is_file_uri ( newfile ) )
|
||||
logpath = gnc_uri_get_path(newfile);
|
||||
PINFO ("logpath=%s", logpath ? logpath : "(null)");
|
||||
xaccLogSetBaseName (logpath);
|
||||
g_free ( logpath );
|
||||
|
||||
|
||||
/* 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);
|
||||
qof_session_destroy(m_session.get());
|
||||
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...
|
||||
*/
|
||||
m_session.reset(new_session);
|
||||
|
||||
qof_event_resume();
|
||||
|
||||
/* --------------- END CORE SESSION CODE -------------- */
|
||||
|
||||
bool r = saveFile();
|
||||
|
||||
save_in_progress--;
|
||||
setCurrentFile(fileName);
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool been_here_before = false;
|
||||
|
||||
bool MainWindow::saveFile()
|
||||
{
|
||||
/* hack alert -- Somehow make sure all in-progress edits get committed! */
|
||||
|
||||
/* If we don't have a filename/path to save to get one. */
|
||||
if (m_session.get_url().isEmpty())
|
||||
return on_actionSave_as_triggered();
|
||||
|
||||
/* use the current session to save to file */
|
||||
save_in_progress++;
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
{
|
||||
// Set up a progress bar in the statusBar()
|
||||
QProgressBar progressBar;
|
||||
progressBar.setMinimum(0);
|
||||
progressBar.setMaximum(100);
|
||||
statusBar()->showMessage(tr("Saving user data..."));
|
||||
statusBar()->addPermanentWidget(&progressBar);
|
||||
progressBar.show();
|
||||
// A local progress_functor to pass the suitable function
|
||||
// pointer to session_load
|
||||
progress_functor functor(&progressBar);
|
||||
|
||||
// The actual saving
|
||||
qof_session_save (m_session.get(), &progress_functor::static_func);
|
||||
|
||||
// Remove the progress bar again from the status bar.
|
||||
statusBar()->removeWidget(&progressBar);
|
||||
}
|
||||
|
||||
// And saving is finished
|
||||
QApplication::restoreOverrideCursor();
|
||||
save_in_progress--;
|
||||
|
||||
|
||||
/* Make sure everything's OK - disk could be full, file could have
|
||||
become read-only etc. */
|
||||
QofBackendError io_err = m_session.get_error ();
|
||||
if (ERR_BACKEND_NO_ERR != io_err)
|
||||
{
|
||||
show_session_error (this, io_err, m_session.get_url(), GNC_FILE_DIALOG_SAVE);
|
||||
|
||||
if (been_here_before)
|
||||
return true;
|
||||
been_here_before = true;
|
||||
on_actionSave_as_triggered();
|
||||
/* been_here prevents infinite recursion */
|
||||
been_here_before = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
xaccReopenLog();
|
||||
gnc_hook_run(HOOK_BOOK_SAVED, m_session.get());
|
||||
|
||||
statusBar()->showMessage(tr("File saved"), 5000);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // END namespace gnc
|
@ -136,7 +136,7 @@ bool MainWindow::on_actionSave_triggered()
|
||||
}
|
||||
else
|
||||
{
|
||||
return saveFile(m_currentFilename);
|
||||
return saveFile();
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ bool MainWindow::on_actionSave_as_triggered()
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
return saveFile(fileName);
|
||||
return saveFileAs(fileName);
|
||||
}
|
||||
|
||||
// Auto-connected to ui->actionAbout's signal triggered()
|
||||
@ -469,12 +469,6 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_book_opened (Session& sess)
|
||||
{
|
||||
gnc_hook_run(HOOK_BOOK_OPENED, sess.get());
|
||||
}
|
||||
|
||||
void MainWindow::newFile()
|
||||
{
|
||||
if (maybeSave())
|
||||
@ -500,334 +494,10 @@ void MainWindow::newFile()
|
||||
gnc_hook_run(HOOK_NEW_BOOK, NULL);
|
||||
|
||||
/* Call this after re-enabling events. */
|
||||
gnc_book_opened (m_session);
|
||||
gnc_hook_run(HOOK_BOOK_OPENED, m_session.get());
|
||||
|
||||
setCurrentFile("");
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
/** This is a workaround function object so that we can obtain a
|
||||
* QofPercentageFunc without extra boost::bind usage; obviously due to
|
||||
* the static member variable it will not work if multiple instances
|
||||
* are in use simultaneously */
|
||||
class progress_functor
|
||||
{
|
||||
public:
|
||||
progress_functor(QProgressBar *progressBar)
|
||||
{
|
||||
m_progressBar = progressBar;
|
||||
}
|
||||
~progress_functor()
|
||||
{
|
||||
m_progressBar = NULL;
|
||||
}
|
||||
static void static_func(const char *message, double percent)
|
||||
{
|
||||
assert(m_progressBar);
|
||||
m_progressBar->setValue(int(percent));
|
||||
// Give the Qt event loop some time
|
||||
qApp->processEvents();
|
||||
}
|
||||
private:
|
||||
static QProgressBar *m_progressBar;
|
||||
};
|
||||
QProgressBar *progress_functor::m_progressBar = NULL;
|
||||
|
||||
} // END namespace anonymous
|
||||
|
||||
|
||||
void MainWindow::loadFile(const QString &fileName)
|
||||
{
|
||||
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 -- */
|
||||
m_session.call_close_hooks();
|
||||
gnc_hook_run(HOOK_BOOK_CLOSED, m_session.get());
|
||||
qof_session_destroy(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 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"));
|
||||
if (QMessageBox::question(this, fmt1, fmt2,
|
||||
QMessageBox::Ok | QMessageBox::Cancel)
|
||||
== 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 | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok)
|
||||
{
|
||||
/* user told us to create a new database. Do it. */
|
||||
qof_session_begin (new_session, newfile, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
/* 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))
|
||||
{
|
||||
we_are_in_error = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
if (!we_are_in_error)
|
||||
{
|
||||
char * logpath = gnc_uri_get_path(newfile);
|
||||
PINFO ("logpath=%s", logpath ? logpath : "(null)");
|
||||
xaccLogSetBaseName (logpath);
|
||||
xaccLogDisable();
|
||||
|
||||
{
|
||||
// Set up a progress bar in the statusBar()
|
||||
QProgressBar progressBar;
|
||||
progressBar.setMinimum(0);
|
||||
progressBar.setMaximum(100);
|
||||
statusBar()->showMessage(tr("Loading user data..."));
|
||||
statusBar()->addPermanentWidget(&progressBar);
|
||||
progressBar.show();
|
||||
// This local progress_functor is a workaround on how to
|
||||
// pass the suitable function pointer to session_load -
|
||||
// not very nice because of its static member, but it does
|
||||
// the trick for now.
|
||||
progress_functor functor(&progressBar);
|
||||
|
||||
// Do the loading.
|
||||
qof_session_load (new_session, &progress_functor::static_func);
|
||||
|
||||
// Remove the progress bar again from the status bar. No
|
||||
// explicit delete necessary because it is just a local
|
||||
// variable.
|
||||
statusBar()->removeWidget(&progressBar);
|
||||
}
|
||||
xaccLogEnable();
|
||||
|
||||
/* check for i/o error, put up appropriate error dialog */
|
||||
io_err = qof_session_get_error (new_session);
|
||||
|
||||
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. Continue? FIXME")
|
||||
.arg(fileName)
|
||||
.arg(errorToString(io_err))
|
||||
.arg(errorToDescription(io_err)),
|
||||
QMessageBox::Ok | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* if we got to here, then we've successfully gotten a new session */
|
||||
/* close up the old file session (if any) */
|
||||
if (m_session.get())
|
||||
{
|
||||
qof_session_destroy(m_session.get());
|
||||
m_session.reset();
|
||||
}
|
||||
m_session.reset(new_session);
|
||||
|
||||
qof_event_resume ();
|
||||
|
||||
/* Call this after re-enabling events. */
|
||||
gnc_book_opened (m_session);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// Some display about this file
|
||||
|
||||
Account root (m_session.get_book().get_root_account());
|
||||
if (root)
|
||||
{
|
||||
m_accountListModel = new AccountListModel(root, this);
|
||||
ui->tableView->setModel(m_accountListModel);
|
||||
|
||||
m_accountTreeModel = new AccountTreeModel(root, this);
|
||||
ui->treeView->setModel(m_accountTreeModel);
|
||||
|
||||
ui->treeViewTab->setProperty(PROPERTY_TAB_PREVIOUSPOS, ui->tabWidget->currentIndex());
|
||||
ui->tabWidget->setCurrentWidget(ui->treeViewTab);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ui->labelMain->setText(tr("No root account"));
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
setCurrentFile(fileName);
|
||||
statusBar()->showMessage(tr("File loaded"), 5000);
|
||||
}
|
||||
|
||||
bool MainWindow::saveFile(const QString &fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (!file.open(QFile::WriteOnly))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Application"),
|
||||
tr("Cannot write file %1:\n%2.")
|
||||
.arg(fileName)
|
||||
.arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
QofSession *session = m_session.get();
|
||||
/* 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 | QMessageBox::Cancel)
|
||||
== 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),
|
||||
QMessageBox::Ok | QMessageBox::Cancel)
|
||||
== QMessageBox::Ok)
|
||||
{
|
||||
/* 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: %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
|
||||
* 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);
|
||||
qof_session_destroy(m_session.get());
|
||||
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...
|
||||
*/
|
||||
m_session.reset(new_session);
|
||||
|
||||
qof_event_resume();
|
||||
|
||||
/* --------------- END CORE SESSION CODE -------------- */
|
||||
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
setCurrentFile(fileName);
|
||||
statusBar()->showMessage(tr("File saved"), 2000);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // END namespace gnc
|
||||
|
@ -87,14 +87,28 @@ private:
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
bool maybeSave();
|
||||
void loadFile(const QString &fileName);
|
||||
bool saveFile(const QString &fileName);
|
||||
void setCurrentFile(const QString &fileName);
|
||||
QString strippedName(const QString &fullFileName);
|
||||
void viewOrHideTab(bool checkedView, QWidget *widget);
|
||||
void reallyRemoveTab(int index);
|
||||
void updateWindowTitle();
|
||||
|
||||
void loadFile(const QString &fileName);
|
||||
bool saveFile();
|
||||
bool saveFileAs(const QString &fileName);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GNC_FILE_DIALOG_OPEN,
|
||||
GNC_FILE_DIALOG_IMPORT,
|
||||
GNC_FILE_DIALOG_SAVE,
|
||||
GNC_FILE_DIALOG_EXPORT
|
||||
} GNCFileDialogType;
|
||||
static bool show_session_error (QWidget *parent,
|
||||
::QofBackendError io_error,
|
||||
const QString& newfile,
|
||||
GNCFileDialogType type);
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
QString m_currentFilename;
|
||||
|
@ -10,11 +10,9 @@ INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}/lib/libc) # for strptime.h
|
||||
|
||||
|
||||
# Workaround to create a very simple gncla-dir.h file
|
||||
FILE (WRITE ${CMAKE_CURRENT_BINARY_DIR}/qofla-dir.h.tmp "
|
||||
FILE (WRITE ${CMAKE_CURRENT_BINARY_DIR}/qofla-dir.h "
|
||||
#define QOF_LIB_DIR \"${CMAKE_INSTALL_PREFIX}/lib/gnucash\"
|
||||
")
|
||||
# Let cmake copy the created file only on changes.
|
||||
CONFIGURE_FILE (${CMAKE_CURRENT_BINARY_DIR}/qofla-dir.h.tmp ${CMAKE_CURRENT_BINARY_DIR}/qofla-dir.h COPYONLY)
|
||||
|
||||
INCLUDE_DIRECTORIES (${CMAKE_CURRENT_BINARY_DIR}) # for qofla-dir.h
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user