summaryrefslogtreecommitdiffstats
path: root/kexi/main
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/main
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kexi/main')
-rw-r--r--kexi/main/Makefile.am35
-rw-r--r--kexi/main/configure.in.in102
-rw-r--r--kexi/main/kde2_closebutton.xpm22
-rw-r--r--kexi/main/kexifinddialog.cpp279
-rw-r--r--kexi/main/kexifinddialog.h130
-rw-r--r--kexi/main/kexifinddialogbase.ui357
-rw-r--r--kexi/main/keximainwindowimpl.cpp4641
-rw-r--r--kexi/main/keximainwindowimpl.h538
-rw-r--r--kexi/main/keximainwindowimpl_p.h599
-rw-r--r--kexi/main/kexinamedialog.cpp111
-rw-r--r--kexi/main/kexinamedialog.h61
-rw-r--r--kexi/main/kexinamewidget.cpp236
-rw-r--r--kexi/main/kexinamewidget.h142
-rw-r--r--kexi/main/kexinewstuff.cpp81
-rw-r--r--kexi/main/kexinewstuff.h41
-rw-r--r--kexi/main/kexistatusbar.cpp145
-rw-r--r--kexi/main/kexistatusbar.h77
-rw-r--r--kexi/main/ksplitter.h256
-rw-r--r--kexi/main/printing/Makefile.am32
-rw-r--r--kexi/main/printing/kexisimpleprintingengine.cpp558
-rw-r--r--kexi/main/printing/kexisimpleprintingengine.h130
-rw-r--r--kexi/main/printing/kexisimpleprintingpagesetup.cpp550
-rw-r--r--kexi/main/printing/kexisimpleprintingpagesetup.h117
-rw-r--r--kexi/main/printing/kexisimpleprintingpagesetupbase.ui447
-rw-r--r--kexi/main/printing/kexisimpleprintingpart.cpp63
-rw-r--r--kexi/main/printing/kexisimpleprintingpart.h51
-rw-r--r--kexi/main/printing/kexisimpleprintpreviewwindow.cpp381
-rw-r--r--kexi/main/printing/kexisimpleprintpreviewwindow.h83
-rw-r--r--kexi/main/printing/kexisimpleprintpreviewwindow_p.h55
-rw-r--r--kexi/main/startup/KexiConnSelector.cpp432
-rw-r--r--kexi/main/startup/KexiConnSelector.h142
-rw-r--r--kexi/main/startup/KexiConnSelectorBase.ui285
-rw-r--r--kexi/main/startup/KexiDBTitlePage.cpp35
-rw-r--r--kexi/main/startup/KexiDBTitlePage.h42
-rw-r--r--kexi/main/startup/KexiDBTitlePageBase.ui94
-rw-r--r--kexi/main/startup/KexiNewPrjTypeSelector.ui94
-rw-r--r--kexi/main/startup/KexiNewProjectWizard.cpp422
-rw-r--r--kexi/main/startup/KexiNewProjectWizard.h90
-rw-r--r--kexi/main/startup/KexiOpenExistingFile.ui127
-rw-r--r--kexi/main/startup/KexiProjectSelector.cpp297
-rw-r--r--kexi/main/startup/KexiProjectSelector.h134
-rw-r--r--kexi/main/startup/KexiProjectSelectorBase.ui128
-rw-r--r--kexi/main/startup/KexiServerDBNamePage.ui141
-rw-r--r--kexi/main/startup/KexiStartup.cpp965
-rw-r--r--kexi/main/startup/KexiStartup.h136
-rw-r--r--kexi/main/startup/KexiStartupDialog.cpp699
-rw-r--r--kexi/main/startup/KexiStartupDialog.h185
-rw-r--r--kexi/main/startup/KexiStartupDialogTemplatesPage.cpp157
-rw-r--r--kexi/main/startup/KexiStartupDialogTemplatesPage.h57
-rw-r--r--kexi/main/startup/KexiStartupFileDialog.cpp422
-rw-r--r--kexi/main/startup/KexiStartupFileDialog.h132
-rw-r--r--kexi/main/startup/KexiStartupFileDialogBase_win.h67
-rw-r--r--kexi/main/startup/KexiStartupFileDialog_win.cpp476
-rw-r--r--kexi/main/startup/KexiStartup_p.cpp127
-rw-r--r--kexi/main/startup/KexiStartup_p.h59
-rw-r--r--kexi/main/startup/Makefile.am47
56 files changed, 16312 insertions, 0 deletions
diff --git a/kexi/main/Makefile.am b/kexi/main/Makefile.am
new file mode 100644
index 00000000..8786c7cf
--- /dev/null
+++ b/kexi/main/Makefile.am
@@ -0,0 +1,35 @@
+include $(top_srcdir)/kexi/Makefile.global
+
+lib_LTLIBRARIES = libkeximain.la
+libkeximain_la_SOURCES = \
+ keximainwindowimpl.cpp \
+ kexistatusbar.cpp \
+ kexinamewidget.cpp kexinamedialog.cpp \
+ kexinewstuff.cpp kexifinddialogbase.ui kexifinddialog.cpp
+
+libkeximain_la_LDFLAGS = -no-undefined $(KDE_RPATH) $(all_libraries) \
+ $(VER_INFO) -Wnounresolved
+
+SUBDIRS = startup printing .
+
+libkeximain_la_LIBADD = $(top_builddir)/kexi/kexidb/libkexidb.la $(top_builddir)/kexi/core/libkexicore.la \
+ $(top_builddir)/kexi/kexiutils/libkexiutils.la \
+ $(top_builddir)/kexi/main/startup/libkeximainstartup.la \
+ $(top_builddir)/kexi/main/printing/libkeximainprinting.la \
+ $(top_builddir)/lib/koproperty/libkoproperty.la \
+ $(top_builddir)/kexi/widget/libkexiextendedwidgets.la \
+ $(LIB_KFEEDBACK) $(LIB_KEXI_KMDI) $(LIB_KNEWSTUFF) $(LIB_KIO) $(LIB_KDEPRINT)
+
+#disabled ../migration/libkeximigrate.la
+
+INCLUDES = $(INC_KFEEDBACK) $(LIB_KEXI_KMDI_INCLUDES) \
+ -I$(top_builddir)/lib/kofficeui -I$(top_srcdir)/lib/kofficeui \
+ -I$(top_srcdir)/kexi -I$(top_srcdir)/kexi/core \
+ -I$(top_srcdir)/kexi/main \
+ -I$(top_srcdir)/kexi/main/startup -I$(top_srcdir)/kexi/widget \
+ -I$(top_srcdir)/kexi/migration -I$(top_srcdir)/lib -I$(top_srcdir)/lib/kofficecore \
+ $(all_includes)
+
+noinst_HEADERS = ksplitter.h keximainwindowimpl_p.h
+
+METASOURCES = AUTO
diff --git a/kexi/main/configure.in.in b/kexi/main/configure.in.in
new file mode 100644
index 00000000..00c25f38
--- /dev/null
+++ b/kexi/main/configure.in.in
@@ -0,0 +1,102 @@
+
+dnl ======================================
+dnl KNewStuff Configuration
+dnl ======================================
+dnl
+dnl Copyright (C) 2004 Josef Spillner <spillner@kde.org>
+dnl This file is to be used within KDE's build system.
+dnl It defines $(LIB_KNEWSTUFF) if knewstuff has been found,
+dnl and a HAVE_KNEWSTUFF #define statement is added.
+dnl
+
+AC_MSG_CHECKING([for KDE library: knewstuff])
+
+ac_knewstuff_includes=NO ac_knewstuff_libraries=NO
+knewstuff_libraries=""
+knewstuff_includes=""
+
+AC_CACHE_VAL(ac_cv_have_knewstuff,
+[
+AC_FIND_FILE(knewstuff/downloaddialog.h, $kde_incdirs, knewstuff_incdir)
+ac_knewstuff_includes="$knewstuff_incdir"
+
+AC_FIND_FILE(libknewstuff.so, $kde_libdirs, knewstuff_libdir)
+ac_knewstuff_libraries="$knewstuff_libdir"
+
+if test "$ac_knewstuff_includes" = NO || test "$ac_knewstuff_libraries" = NO; then
+ ac_cv_have_knewstuff="have_knewstuff=no"
+ ac_knewstuff_notfound=""
+else
+ have_knewstuff="yes"
+fi
+])
+
+eval "$ac_cv_have_knewstuff"
+
+if test "$have_knewstuff" != yes; then
+ AC_MSG_RESULT([$have_knewstuff])
+else
+ AC_MSG_RESULT([$have_knewstuff (libraries $ac_knewstuff_libraries, headers $ac_knewstuff_includes)])
+
+dnl AC_DEFINE_UNQUOTED(HAVE_KNEWSTUFF, 1, [Add KNewStuff functionality.])
+ CXXFLAGS="$CXXFLAGS -DHAVE_KNEWSTUFF"
+
+ LIB_KNEWSTUFF='-lknewstuff'
+ AC_SUBST(LIB_KNEWSTUFF)
+fi
+
+AC_CHECK_FILE([kexi/3rdparty/kexifeedbackwizard/lib/kexifeedbackwizard.cpp],
+ have_internal_feedback="yes"
+,
+ have_internal_feedback="no"
+)
+
+AC_MSG_CHECKING([for KDE library: kfeedbackwizard])
+
+ac_kfeedback_includes=NO ac_kfeedback_libraries=NO
+kfeedback_libraries=""
+kfeedback_includes=""
+
+AC_CACHE_VAL(ac_cv_have_kfeedback,
+[
+AC_FIND_FILE(kfeedbackwizard.h, $kde_incdirs, kfeedback_incdir)
+ac_kfeedback_includes="$kfeedback_incdir"
+
+AC_FIND_FILE(libkfeedbackwizard.so, $kde_libdirs, kfeedback_libdir)
+ac_kfeedback_libraries="$kfeedback_libdir"
+
+if test "$ac_kfeedback_includes" = NO || test "$ac_kfeedback_libraries" = NO; then
+ ac_cv_have_kfeedback="have_kfeedback=no"
+ ac_kfeedback_notfound=""
+else
+ have_kfeedback="yes"
+fi
+])
+
+eval "$ac_cv_have_kfeedback"
+
+INC_KFEEDBACK=''
+LIB_KFEEDBACK=''
+if test "$have_kfeedback" != yes; then
+ if test "$have_internal_feedback" = yes; then
+ CXXFLAGS="$CXXFLAGS -DFEEDBACK_CLASS=KexiFeedbackWizard -DFEEDBACK_INCLUDE=\"<kexifeedbackwizard.h>\""
+ use_kexifb="yes"
+ AC_MSG_RESULT([using internal])
+ INC_KFEEDBACK='-I../3rdparty/kexifeedbackwizard/lib'
+ LIB_KFEEDBACK='../3rdparty/kexifeedbackwizard/lib/libkexifeedbackwizard.la'
+ else
+ use_kexifb="no"
+ AC_MSG_RESULT([dont use])
+ fi
+else
+ use_kexifb="no"
+ AC_MSG_RESULT([$have_kfeedback (libraries $ac_kfeedback_libraries, headers $ac_kfeedback_includes)])
+
+dnl AC_DEFINE_UNQUOTED(HAVE_KFEEDBACK, 1, [Add KNewStuff functionality.])
+ CXXFLAGS="$CXXFLAGS -DFEEDBACK_CLASS=KFeedbackWizard -DFEEDBACK_INCLUDE=\"<kfeedbackwizard.h>\""
+
+ LIB_KFEEDBACK='-lkfeedbackwizard'
+fi
+AC_SUBST(LIB_KFEEDBACK)
+AC_SUBST(INC_KFEEDBACK)
+AM_CONDITIONAL(use_kexifeedback, test "$use_kexifb" = "yes")
diff --git a/kexi/main/kde2_closebutton.xpm b/kexi/main/kde2_closebutton.xpm
new file mode 100644
index 00000000..5c05e714
--- /dev/null
+++ b/kexi/main/kde2_closebutton.xpm
@@ -0,0 +1,22 @@
+/* XPM */
+#ifndef _KDE2_CLOSEBUTTON_XPM_
+#define _KDE2_CLOSEBUTTON_XPM_
+
+static const char* kde2_closebutton[]={
+"12 12 2 1",
+". s None c None",
+"# c #000000",
+"............",
+"............",
+"...#....#...",
+"..###..###..",
+"...######...",
+"....####....",
+"....####....",
+"...######...",
+"..###..###..",
+"...#....#...",
+"............",
+"............"};
+
+#endif
diff --git a/kexi/main/kexifinddialog.cpp b/kexi/main/kexifinddialog.cpp
new file mode 100644
index 00000000..58f693c0
--- /dev/null
+++ b/kexi/main/kexifinddialog.cpp
@@ -0,0 +1,279 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "kexifinddialog.h"
+
+#include <kstdguiitem.h>
+#include <kstdaction.h>
+#include <kpushbutton.h>
+#include <kcombobox.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kaction.h>
+#include <kiconloader.h>
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qguardedptr.h>
+#include <qlayout.h>
+#include <qaccel.h>
+
+//! @internal
+class KexiFindDialog::Private
+{
+ public:
+ Private()
+ {
+ accels.setAutoDelete(true);
+ }
+ ~Private()
+ {
+ }
+ //! Connects action \a action with appropriate signal \a member
+ //! and optionally adds accel that will receive shortcut for \a action
+ //! at global scope of the dialog \a parent.
+ void setActionAndAccel(KAction *action, QWidget* parent, const char* member)
+ {
+ if (!action)
+ return;
+ QObject::connect(parent, member, action, SLOT(activate()));
+ if (action->shortcut().isNull())
+ return;
+ QAccel *accel = new QAccel(parent); // we want to handle dialog-wide shortcut as well
+ accels.append( accel );
+ accel->connectItem(
+ accel->insertItem( action->shortcut() ), parent, member );
+ }
+
+ QStringList lookInColumnNames;
+ QStringList lookInColumnCaptions;
+ QString objectName; //!< for caption
+ QGuardedPtr<KAction> findnextAction;
+ QGuardedPtr<KAction> findprevAction;
+ QGuardedPtr<KAction> replaceAction;
+ QGuardedPtr<KAction> replaceallAction;
+ QPtrList<QAccel> accels;
+ bool replaceMode : 1;
+};
+
+//------------------------------------------
+
+KexiFindDialog::KexiFindDialog( QWidget* parent )
+ : KexiFindDialogBase(parent, "KexiFindDialog", false/*!modal*/,
+ Qt::WType_Dialog|Qt::WStyle_NormalBorder|Qt::WStyle_Title
+ |Qt::WStyle_SysMenu|Qt::WStyle_Customize|Qt::WStyle_Tool)
+ , d( new Private() )
+{
+ m_search->setCurrentItem((int)KexiSearchAndReplaceViewInterface::Options::SearchDown);
+ layout()->setMargin( KDialog::marginHint() );
+ layout()->setSpacing( KDialog::spacingHint() );
+ KAction *a = KStdAction::findNext(0, 0, 0);
+ m_btnFind->setText(a->text());
+ m_btnFind->setIconSet(a->iconSet());
+ delete a;
+ m_btnClose->setText(KStdGuiItem::close().text());
+ m_btnClose->setIconSet(KStdGuiItem::close().iconSet());
+ connect(m_btnFind, SIGNAL(clicked()), this, SIGNAL(findNext()));
+ connect(m_btnClose, SIGNAL(clicked()), this, SLOT(slotCloseClicked()));
+ connect(m_btnReplace, SIGNAL(clicked()), this, SIGNAL(replaceNext()));
+ connect(m_btnReplaceAll, SIGNAL(clicked()), this, SIGNAL(replaceAll()));
+ // clear message after the text is changed
+ connect(m_textToFind, SIGNAL(textChanged()), this, SIGNAL(updateMessage()));
+ connect(m_textToReplace, SIGNAL(textChanged()), this, SIGNAL(updateMessage()));
+
+ d->replaceMode = true; //to force updating by setReplaceMode()
+ setReplaceMode(false);
+
+ setLookInColumnList(QStringList(), QStringList());
+}
+
+KexiFindDialog::~KexiFindDialog()
+{
+ delete d;
+}
+
+void KexiFindDialog::setActions( KAction *findnext, KAction *findprev,
+ KAction *replace, KAction *replaceall )
+{
+ d->findnextAction = findnext;
+ d->findprevAction = findprev;
+ d->replaceAction = replace;
+ d->replaceallAction = replaceall;
+ d->accels.clear();
+ d->setActionAndAccel(d->findnextAction, this, SIGNAL(findNext()));
+ d->setActionAndAccel(d->findprevAction, this, SIGNAL(findPrevious()));
+ d->setActionAndAccel(d->replaceAction, this, SIGNAL(replaceNext()));
+ d->setActionAndAccel(d->replaceallAction, this, SIGNAL(replaceAll()));
+}
+
+QStringList KexiFindDialog::lookInColumnNames() const
+{
+ return d->lookInColumnNames;
+}
+
+QStringList KexiFindDialog::lookInColumnCaptions() const
+{
+ return d->lookInColumnCaptions;
+}
+
+QString KexiFindDialog::currentLookInColumnName() const
+{
+ int index = m_lookIn->currentItem();
+ if (index <= 0 || index >= (int)d->lookInColumnNames.count())
+ return QString::null;
+ else if (index == 1)
+ return "(field)";
+ return d->lookInColumnNames[index - 1/*"(All fields)"*/ - 1/*"(Current field)"*/];
+}
+
+QVariant KexiFindDialog::valueToFind() const
+{
+ return m_textToFind->currentText();
+}
+
+QVariant KexiFindDialog::valueToReplaceWith() const
+{
+ return m_textToReplace->currentText();
+}
+
+void KexiFindDialog::setLookInColumnList(const QStringList& columnNames,
+ const QStringList& columnCaptions)
+{
+ d->lookInColumnNames = columnNames;
+ d->lookInColumnCaptions = columnCaptions;
+ m_lookIn->clear();
+ m_lookIn->insertItem(i18n("(All fields)"));
+ m_lookIn->insertItem(i18n("(Current field)"));
+ m_lookIn->insertStringList(d->lookInColumnCaptions);
+}
+
+void KexiFindDialog::setCurrentLookInColumnName(const QString& columnName)
+{
+ int index;
+ if (columnName.isEmpty())
+ index = 0;
+ else if (columnName == "(field)")
+ index = 1;
+ else {
+ index = d->lookInColumnNames.findIndex( columnName );
+ if (index == -1) {
+ kdWarning() << QString("KexiFindDialog::setCurrentLookInColumn(%1) column name not found on the list")
+ .arg(columnName) << endl;
+ return;
+ }
+ index = index + 1/*"(All fields)"*/ + 1/*"(Current field)"*/;
+ }
+ m_lookIn->setCurrentItem(index);
+}
+
+void KexiFindDialog::setReplaceMode(bool set)
+{
+ if (d->replaceMode == set)
+ return;
+ d->replaceMode = set;
+ if (d->replaceMode) {
+ m_promptOnReplace->show();
+ m_replaceLbl->show();
+ m_textToReplace->show();
+ m_btnReplace->show();
+ m_btnReplaceAll->show();
+ }
+ else {
+ m_promptOnReplace->hide();
+ m_replaceLbl->hide();
+ m_textToReplace->hide();
+ m_btnReplace->hide();
+ m_btnReplaceAll->hide();
+ resize(width(),height()-30);
+ }
+ setObjectNameForCaption(d->objectName);
+ updateGeometry();
+}
+
+void KexiFindDialog::setObjectNameForCaption(const QString& name)
+{
+ d->objectName = name;
+ if (d->replaceMode) {
+ if (name.isEmpty())
+ setCaption(i18n("Replace"));
+ else
+ setCaption(i18n("Replace in \"%1\"").arg(name));
+ }
+ else {
+ if (name.isEmpty())
+ setCaption(i18n("Find"));
+ else
+ setCaption(i18n("Find in \"%1\"").arg(name));
+ }
+}
+
+void KexiFindDialog::setButtonsEnabled(bool enable)
+{
+ m_btnFind->setEnabled(enable);
+ m_btnReplace->setEnabled(enable);
+ m_btnReplaceAll->setEnabled(enable);
+ if (!enable)
+ setObjectNameForCaption(QString::null);
+}
+
+void KexiFindDialog::setMessage(const QString& message)
+{
+ m_messageLabel->setText(message);
+}
+
+void KexiFindDialog::updateMessage( bool found )
+{
+ if (found)
+ setMessage(QString::null);
+ else
+ setMessage(i18n("The search item was not found"));
+}
+
+void KexiFindDialog::slotCloseClicked()
+{
+ reject();
+}
+
+void KexiFindDialog::show()
+{
+ m_textToFind->setFocus();
+ QDialog::show();
+}
+
+KexiSearchAndReplaceViewInterface::Options KexiFindDialog::options() const
+{
+ KexiSearchAndReplaceViewInterface::Options options;
+ if (m_lookIn->currentItem() <= 0) //"(All fields)"
+ options.columnNumber = KexiSearchAndReplaceViewInterface::Options::AllColumns;
+ else if (m_lookIn->currentItem() == 1) //"(Current field)"
+ options.columnNumber = KexiSearchAndReplaceViewInterface::Options::CurrentColumn;
+ else
+ options.columnNumber = m_lookIn->currentItem() - 1/*"(All fields)"*/ - 1/*"(Current field)"*/;
+ options.textMatching
+ = (KexiSearchAndReplaceViewInterface::Options::TextMatching)m_match->currentItem();
+ options.searchDirection
+ = (KexiSearchAndReplaceViewInterface::Options::SearchDirection)m_search->currentItem();
+ options.caseSensitive = m_caseSensitive->isChecked();
+ options.wholeWordsOnly = m_wholeWords->isChecked();
+ options.promptOnReplace = m_promptOnReplace->isChecked();
+ return options;
+}
+
+#include "kexifinddialog.moc"
diff --git a/kexi/main/kexifinddialog.h b/kexi/main/kexifinddialog.h
new file mode 100644
index 00000000..ea7777e0
--- /dev/null
+++ b/kexi/main/kexifinddialog.h
@@ -0,0 +1,130 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXIFINDDIALOG_H
+#define KEXIFINDDIALOG_H
+
+#include "kexifinddialogbase.h"
+#include <core/kexisearchandreplaceiface.h>
+
+class KAction;
+
+//! @short A Kexi-specific "Find text" dialog.
+/*! Also used for as replace dialog.
+
+ @todo replace m_textToFind and m_textToReplace KComboBoxes with Kexi's db-aware comboboxes,
+ so we ca adapt to datatype being searched, e.g. date, time and numbers
+*/
+class KexiFindDialog : public KexiFindDialogBase
+{
+ Q_OBJECT
+ public:
+ //! Creates a new find dialog. Replace mode is off by default.
+ KexiFindDialog(QWidget* parent);
+ virtual ~KexiFindDialog();
+
+ //! Sets actions that receive button clicks and shortcuts within the dialog. Should be called once.
+ void setActions( KAction *findnext, KAction *findprev,
+ KAction *replace, KAction *replaceall );
+
+ //! Shows the dialog as a modal dialog.
+ virtual void show();
+
+ //! \return current find and replace options set within the dialog
+//! @todo should we have setOptions() too?
+ KexiSearchAndReplaceViewInterface::Options options() const;
+
+ /*! \return a list of column names for 'look in column' combo box.
+ Neither "(All fields)" nor "(Current field)" items are prepended. */
+ QStringList lookInColumnNames() const;
+
+ /*! \return a list of column captions (i.e. visible values) for 'look in column' combo box.
+ Neither "(All fields)" nor "(Current field)" items are prepended. */
+ QStringList lookInColumnCaptions() const;
+
+ /*! \return column name selected in "look in column" combo box.
+ If "(All fields)" item is selected, empty string is returned.
+ If "(Current field)" item is selected, "(field)" string is returned. */
+ QString currentLookInColumnName() const;
+
+ //! \return value that to be used for searching
+ QVariant valueToFind() const;
+
+ //! \return value that to be used as a replacement
+ QVariant valueToReplaceWith() const;
+
+ public slots:
+ /*! Sets \a columnNames list and \a columnCaptions for 'look in column' combo box.
+ \a columnCaptions are visible values, while \a columnNames are used for returning
+ in currentLookInColumn().
+ "(All fields)" and "(Current field)" items are also prepended. */
+ void setLookInColumnList(const QStringList& columnNames,
+ const QStringList& columnCaptions);
+
+ /*! Selects \a columnName to be selected 'look in column'.
+ By default "(All fields)" item is selected. To select this item,
+ pass empty string as \a columnName.
+ To select "(Current field)" item, "(field)" string should be passed
+ as \a columnName. */
+ void setCurrentLookInColumnName(const QString& columnName);
+
+ /*! Sets or clears replace mode.
+ For replace mode 'prompt or replace' option is visible. */
+ void setReplaceMode(bool set);
+
+ /*! Sets object name for caption, so for example it will be set
+ to i18n("Find \"Persons\"")). */
+ void setObjectNameForCaption(const QString& name);
+
+ /*! Enables of disables the find/replace/replace all buttons.
+ This is used if for the current context the dialog could not be used.
+ If \a enable is false, object name for caption is cleared
+ using setObjectNameForCaption() too. */
+ void setButtonsEnabled(bool enable);
+
+ /*! Sets message at the bottom to \a message. */
+ void setMessage(const QString& message);
+
+ /*! Updates message at the bottom; "The search item was not found" is set if \a found is true,
+ else the message is cleared. */
+//! @todo add "Search again" hyperlink
+ void updateMessage( bool found = true );
+
+ signals:
+ //! Emitted after clicking "Find next" button or pressing appropriate shortcut set by setActions()
+ void findNext();
+
+ //! Emitted after pressing appropriate shortcut set by setActions()
+ void findPrevious();
+
+ //! Emitted after clicking "Replace" button or pressing appropriate shortcut set by setActions()
+ void replaceNext();
+
+ //! Emitted after clicking "Replace All" button or pressing appropriate shortcut set by setActions()
+ void replaceAll();
+
+ protected slots:
+ void slotCloseClicked();
+
+ protected:
+ class Private;
+ Private * const d;
+};
+
+#endif
diff --git a/kexi/main/kexifinddialogbase.ui b/kexi/main/kexifinddialogbase.ui
new file mode 100644
index 00000000..3ba82bb5
--- /dev/null
+++ b/kexi/main/kexifinddialogbase.ui
@@ -0,0 +1,357 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KexiFindDialogBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>KexiFindDialogBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>472</width>
+ <height>247</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Find</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Fi&amp;nd:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_textToFind</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>m_replaceLbl</cstring>
+ </property>
+ <property name="text">
+ <string>Re&amp;place with:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_textToReplace</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>m_lookIn</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>StrongFocus</enum>
+ </property>
+ <property name="insertionPolicy">
+ <enum>NoInsertion</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Look in:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_lookIn</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="5" column="2">
+ <property name="name">
+ <cstring>m_wholeWords</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>WheelFocus</enum>
+ </property>
+ <property name="text">
+ <string>&amp;Whole words only</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="6" column="2">
+ <property name="name">
+ <cstring>m_promptOnReplace</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>WheelFocus</enum>
+ </property>
+ <property name="text">
+ <string>Prompt on replace</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="4" rowspan="7" colspan="1">
+ <property name="name">
+ <cstring>layout_btn</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>m_btnFind</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>m_btnClose</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>m_btnReplace</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Replace</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>m_btnReplaceAll</cstring>
+ </property>
+ <property name="text">
+ <string>Replace All</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Match:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_match</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="4" column="1">
+ <item>
+ <property name="text">
+ <string>Any Part of Field</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Whole Field</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Start of Field</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_match</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>StrongFocus</enum>
+ </property>
+ <property name="insertionPolicy">
+ <enum>NoInsertion</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Search:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_search</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="1">
+ <item>
+ <property name="text">
+ <string>Up</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Down</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>All Rows</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_search</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>StrongFocus</enum>
+ </property>
+ <property name="insertionPolicy">
+ <enum>NoInsertion</enum>
+ </property>
+ </widget>
+ <spacer row="7" column="2">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>2</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="4" column="2">
+ <property name="name">
+ <cstring>m_caseSensitive</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>WheelFocus</enum>
+ </property>
+ <property name="text">
+ <string>C&amp;ase sensitive</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="8" column="0" rowspan="1" colspan="5">
+ <property name="name">
+ <cstring>m_messageLabel</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer row="4" column="3">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>70</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KHistoryCombo" row="0" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_textToFind</cstring>
+ </property>
+ <property name="insertionPolicy">
+ <enum>AtTop</enum>
+ </property>
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="KHistoryCombo" row="1" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_textToReplace</cstring>
+ </property>
+ <property name="insertionPolicy">
+ <enum>AtTop</enum>
+ </property>
+ <property name="autoCompletion">
+ <bool>true</bool>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_btnClose</sender>
+ <signal>clicked()</signal>
+ <receiver>KexiFindDialogBase</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_textToFind</tabstop>
+ <tabstop>m_textToReplace</tabstop>
+ <tabstop>m_btnFind</tabstop>
+ <tabstop>m_btnClose</tabstop>
+ <tabstop>m_btnReplace</tabstop>
+ <tabstop>m_btnReplaceAll</tabstop>
+ <tabstop>m_lookIn</tabstop>
+ <tabstop>m_search</tabstop>
+ <tabstop>m_match</tabstop>
+ <tabstop>m_caseSensitive</tabstop>
+ <tabstop>m_wholeWords</tabstop>
+ <tabstop>m_promptOnReplace</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kexi/main/keximainwindowimpl.cpp b/kexi/main/keximainwindowimpl.cpp
new file mode 100644
index 00000000..d5ce9939
--- /dev/null
+++ b/kexi/main/keximainwindowimpl.cpp
@@ -0,0 +1,4641 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "keximainwindowimpl.h"
+
+#include <unistd.h>
+
+#include <qapplication.h>
+#include <qeventloop.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <qobjectlist.h>
+#include <qprocess.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+#include <qfiledialog.h>
+#include <qdockwindow.h>
+#include <qdockarea.h>
+
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaction.h>
+#include <klocale.h>
+#include <kstdaccel.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kdebug.h>
+#include <kkeydialog.h>
+#include <kedittoolbar.h>
+#include <kdeversion.h>
+#include <kglobalsettings.h>
+#include <kparts/componentfactory.h>
+#include <ktip.h>
+#include <kstandarddirs.h>
+#include <kpushbutton.h>
+#include <ktextbrowser.h>
+#include <kiconloader.h>
+#include <ktabwidget.h>
+#include <kimageio.h>
+#include <khelpmenu.h>
+#include <kfiledialog.h>
+#include <krecentdocument.h>
+
+#include <kexidb/connection.h>
+#include <kexidb/utils.h>
+#include <kexidb/cursor.h>
+#include <kexidb/dbobjectnamevalidator.h>
+#include <kexidb/admin.h>
+#include <kexiutils/utils.h>
+
+//#include "projectsettingsui.h"
+#include "kexiactionproxy.h"
+#include "kexidialogbase.h"
+#include "kexipartmanager.h"
+#include "kexipart.h"
+#include "kexipartinfo.h"
+#include "kexipartguiclient.h"
+#include "kexiproject.h"
+#include "kexiprojectdata.h"
+#include "kexiprojectset.h"
+#include "kexi.h"
+#include "kexistatusbar.h"
+#include "kexiinternalpart.h"
+#include "kexiactioncategories.h"
+#include "kexifinddialog.h"
+#include "kexisearchandreplaceiface.h"
+
+#include "kde2_closebutton.xpm"
+
+#include <widget/kexibrowser.h>
+#include <widget/kexipropertyeditorview.h>
+#include <widget/utils/kexirecordnavigator.h>
+#include <koproperty/editor.h>
+#include <koproperty/set.h>
+
+#include "startup/KexiStartup.h"
+#include "startup/KexiNewProjectWizard.h"
+#include "startup/KexiStartupDialog.h"
+#include "startup/KexiStartupFileDialog.h"
+#include "kexinamedialog.h"
+#include "printing/kexisimpleprintingpart.h"
+#include "printing/kexisimpleprintingpagesetup.h"
+
+//Extreme verbose debug
+#if defined(Q_WS_WIN)
+# include <krecentdirs.h>
+# include <win32_utils.h>
+//# define KexiVDebug kdDebug()
+#endif
+
+#if !defined(KexiVDebug)
+# define KexiVDebug if (0) kdDebug()
+#endif
+
+//first fix the geometry
+//#define KEXI_NO_CTXT_HELP 1
+
+#ifndef KEXI_NO_CTXT_HELP
+#include <kexicontexthelp.h>
+#endif
+
+#ifdef HAVE_KNEWSTUFF
+#include <knewstuff/downloaddialog.h>
+#include "kexinewstuff.h"
+#endif
+
+//! @todo REENABLE when blinking and dock
+//! width changes will be removed in KMDI
+//#define PROPEDITOR_VISIBILITY_CHANGES
+
+//temporary fix to manage layout
+#include "ksplitter.h"
+#define KDOCKWIDGET_P 1
+
+#ifndef KEXI_NO_FEEDBACK_AGENT
+#ifdef FEEDBACK_INCLUDE
+#include FEEDBACK_INCLUDE
+#endif
+#include <kapplication.h>
+#include <kaboutdata.h>
+#endif
+
+#include "keximainwindowimpl_p.h"
+
+//-------------------------------------------------
+
+//static
+int KexiMainWindowImpl::create(int argc, char *argv[], KAboutData* aboutdata)
+{
+ Kexi::initCmdLineArgs( argc, argv, aboutdata );
+
+ bool GUIenabled = true;
+ QWidget *dummyWidget = 0; //needed to have icon for dialogs before KexiMainWindowImpl is created
+//! @todo switch GUIenabled off when needed
+ KApplication* app = new KApplication(true, GUIenabled);
+
+#ifdef KEXI_STANDALONE
+ KGlobal::locale()->removeCatalogue("kexi");
+ KGlobal::locale()->insertCatalogue("standalone_kexi");
+#endif
+ KGlobal::locale()->insertCatalogue("koffice");
+ KGlobal::locale()->insertCatalogue("koproperty");
+
+#ifdef CUSTOM_VERSION
+# include "custom_exec.h"
+#endif
+
+#ifdef KEXI_DEBUG_GUI
+ QWidget* debugWindow = 0;
+#endif
+ if (GUIenabled) {
+ dummyWidget = new QWidget();
+ dummyWidget->setIcon( DesktopIcon( "kexi" ) );
+ app->setMainWidget(dummyWidget);
+#ifdef KEXI_DEBUG_GUI
+ app->config()->setGroup("General");
+ if (app->config()->readBoolEntry("showInternalDebugger", false)) {
+ debugWindow = KexiUtils::createDebugWindow(0);
+ }
+#endif
+ }
+
+ tristate res = Kexi::startupHandler().init(argc, argv);
+ if (!res || ~res) {
+#ifdef KEXI_DEBUG_GUI
+ delete debugWindow;
+#endif
+ delete app;
+ return (~res) ? 0 : 1;
+ }
+
+ kdDebug() << "startupActions OK" <<endl;
+
+ /* Exit requested, e.g. after database removing. */
+ if (Kexi::startupHandler().action() == KexiStartupData::Exit) {
+#ifdef KEXI_DEBUG_GUI
+ delete debugWindow;
+#endif
+ delete app;
+ return 0;
+ }
+
+ KexiMainWindowImpl *win = new KexiMainWindowImpl();
+ app->setMainWidget(win);
+#ifdef KEXI_DEBUG_GUI
+ //if (debugWindow)
+ //debugWindow->reparent(win, QPoint(1,1));
+#endif
+ delete dummyWidget;
+
+ if (true != win->startup()) {
+ delete win;
+ delete app;
+ return 1;
+ }
+
+ win->show();
+ app->processEvents();//allow refresh our app
+
+//#ifdef KEXI_DEBUG_GUI
+// delete debugWindow;
+//#endif
+ return 0;
+}
+
+//-------------------------------------------------
+
+KexiMainWindowImpl::KexiMainWindowImpl()
+ : KexiMainWindow()
+ , KexiGUIMessageHandler(this)
+ , d(new KexiMainWindowImpl::Private(this) )
+{
+ KImageIO::registerFormats();
+ KexiProjectData *pdata = Kexi::startupHandler().projectData();
+ d->userMode = Kexi::startupHandler().forcedUserMode() /* <-- simply forced the user mode */
+ /* project has 'user mode' set as default and not 'design mode' override is found: */
+ || (pdata && pdata->userMode() && !Kexi::startupHandler().forcedDesignMode());
+ d->isProjectNavigatorVisible = Kexi::startupHandler().isProjectNavigatorVisible();
+
+ if(userMode())
+ kdDebug() << "KexiMainWindowImpl::KexiMainWindowImpl(): starting up in the User Mode" << endl;
+
+ d->config = kapp->config();
+
+ if ( !initialGeometrySet() ) {
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+ d->config->setGroup("MainWindow");
+ QSize s ( d->config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 700 ),
+ d->config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 480 ) );
+ resize (kMin (s.width(), desk.width()), kMin(s.height(), desk.height()));
+ }
+
+ setManagedDockPositionModeEnabled(true);//TODO(js): remove this if will be default in kmdi :)
+ manager()->setSplitterHighResolution(true);
+ manager()->setSplitterKeepSize(true);
+ setStandardMDIMenuEnabled(false);
+ setAsDefaultHost(); //this is default host now.
+ KGlobal::iconLoader()->addAppDir("kexi");
+ KGlobal::iconLoader()->addAppDir("koffice");
+
+ //get informed
+ connect(&Kexi::partManager(),SIGNAL(partLoaded(KexiPart::Part*)),this,SLOT(slotPartLoaded(KexiPart::Part*)));
+ connect( m_pMdi, SIGNAL(nowMaximized(bool)), this, SLOT(slotCaptionForCurrentMDIChild(bool)) );
+ connect( m_pMdi, SIGNAL(noMaximizedChildFrmLeft(KMdiChildFrm*)), this, SLOT(slotNoMaximizedChildFrmLeft(KMdiChildFrm*)));
+// connect( this, SIGNAL(lastChildFrmClosed()), this, SLOT(slotLastChildFrmClosed()));
+ connect( this, SIGNAL(lastChildViewClosed()), this, SLOT(slotLastChildViewClosed()));
+
+ connect( this, SIGNAL(childViewIsDetachedNow(QWidget*)), this, SLOT(slotChildViewIsDetachedNow(QWidget*)));
+ connect( this, SIGNAL(mdiModeHasBeenChangedTo(KMdi::MdiMode)),
+ this, SLOT(slotMdiModeHasBeenChangedTo(KMdi::MdiMode)));
+
+
+ //if (!userMode()) {
+ setXMLFile("kexiui.rc");
+ setAcceptDrops(true);
+ initActions();
+ createShellGUI(true);
+ //}
+
+ d->statusBar = new KexiStatusBar(this, "status_bar");
+
+ d->origAppCaption = caption();
+
+ restoreSettings();
+ (void)Kexi::smallFont(this/*init*/);
+
+ if (!userMode()) {
+ initContextHelp();
+ initPropertyEditor();
+ }
+
+ {//store menu popups list
+ QObjectList *l = queryList( "QPopupMenu" );
+ for (QObjectListIt it( *l ); it.current(); ++it ) {
+ //kdDebug() << "name=" <<it.current()->name() << " cname="<<it.current()->className()<<endl;
+ //KexiMainWindowImpl::eventFilter() will filter our popups:
+ it.current()->installEventFilter(this);
+ d->popups.insert(it.current()->name(), static_cast<QPopupMenu*>(it.current()));
+ }
+ delete l;
+ d->createMenu = d->popups["create"];
+
+#ifdef KEXI_NO_REPORTBUG_COMMAND
+ //remove "bug report" action to avoid confusion for supported with commercial technical support
+ QPopupMenu *helpMenu = d->popups["help"];
+ if (helpMenu) {
+ //const int idx = helpMenu->indexOf( (int)KHelpMenu::menuReportBug );
+ helpMenu->removeItemAt(int(KHelpMenu::menuReportBug)-1);
+ helpMenu->removeItemAt(int(KHelpMenu::menuReportBug)-1); //separator
+ }
+#endif
+ }
+
+ //fix menus a bit more:
+#ifndef KEXI_SHOW_UNIMPLEMENTED
+//disabled (possible crash) d->hideMenuItem("file", i18n("&Import"), true);
+//disabled (possible crash) d->hideMenuItem("help", i18n( "&Report Bug..." ), true);
+#endif
+ KAction *kmdi_tooldock_menu_action = childClients()->getFirst() ? childClients()->getFirst()->actionCollection()->action("kmdi_tooldock_menu") : 0;
+ if (kmdi_tooldock_menu_action) {
+ kmdi_tooldock_menu_action->setEnabled(false);
+ }
+
+ if (!isFakingSDIApplication()/* && !userMode()*/) {
+// QPopupMenu *menu = (QPopupMenu*) child( "window", "KPopupMenu" );
+ QPopupMenu *menu = d->popups["window"];
+ unsigned int count = menuBar()->count();
+ if (menu)
+ setWindowMenu(menu);
+ else
+ menuBar()->insertItem( i18n("&Window"), windowMenu(), -1, count-2); // standard position is left to the last ('Help')
+ }
+ if (userMode()) {
+ //hide "insert" menu and disable "project_import", "edit_paste_special" menus
+ QPopupMenu *menu = d->popups["insert"];
+ if (menu) {
+ for (uint i=0; i < menuBar()->count(); i++) {
+ if (menuBar()->text( menuBar()->idAt(i) ) == i18n("&Insert")) {
+ menuBar()->setItemVisible( menuBar()->idAt(i), false );
+ break;
+ }
+ }
+ }
+ d->disableMenuItem("file", i18n("&Import"));
+ d->disableMenuItem("edit", i18n("Paste &Special"));
+ }
+
+ m_pTaskBar->setCaption(i18n("Task Bar")); //js TODO: move this to KMDIlib
+
+// if (!userMode()) {
+ invalidateActions();
+ d->timer.singleShot(0,this,SLOT(slotLastActions()));
+// }
+
+ setTabWidgetVisibility(KMdi::AlwaysShowTabs);
+ if (mdiMode()==KMdi::IDEAlMode) {
+ d->config->setGroup("MainWindow");
+ tabWidget()->setHoverCloseButton(d->config->readBoolEntry("HoverCloseButtonForTabs", false));
+ //create special close button as corner widget for IDEAl mode
+ QToolButton *closeButton = new QToolButton( tabWidget() );
+ closeButton->setAutoRaise( true );
+ closeButton->setPixmap( QPixmap( kde2_closebutton ) );
+ closeButton->setPaletteBackgroundColor(closeButton->palette().active().background());
+// closeButton->setIconSet(SmallIconSet("tab_remove"));
+ tabWidget()->setCornerWidget( closeButton, Qt::TopRight );
+ closeButton->hide(); // hide until it's needed to avoid problems in "user mode"
+ // when initially the main window is empty
+ QToolTip::add(closeButton,
+ i18n("Close the current tab page in Kexi tab interface", "Close the current tab"));
+ QObject::connect( closeButton, SIGNAL( clicked() ), this, SLOT( closeActiveView() ) );
+ }
+
+#ifdef KEXI_ADD_CUSTOM_KEXIMAINWINDOWIMPL
+# include "keximainwindowimpl_ctor.h"
+#endif
+}
+
+KexiMainWindowImpl::~KexiMainWindowImpl()
+{
+ d->forceDialogClosing=true;
+ closeProject();
+ delete d;
+}
+
+KexiProject *KexiMainWindowImpl::project()
+{
+ return d->prj;
+}
+
+void KexiMainWindowImpl::setWindowMenu(QPopupMenu *menu)
+{
+ delete m_pWindowMenu;
+ m_pWindowMenu = menu;
+ int count = menuBar()->count();
+ //try to move "window" menu just before "Settings" menu (count-3)
+ const QString txt = i18n("&Window");
+ int i;
+ for (i=0; i<count; i++) {
+ //kdDebug() << menuBar()->text( menuBar()->idAt(i) ) << endl;
+ if (txt==menuBar()->text( menuBar()->idAt(i) ))
+ break;
+ }
+ if (i<count) {
+ const int id = menuBar()->idAt(i);
+ menuBar()->removeItemAt(i);
+ menuBar()->insertItem(txt, m_pWindowMenu, id, count-3);
+ }
+ m_pWindowMenu->setCheckable(true);
+ QObject::connect( m_pWindowMenu, SIGNAL(aboutToShow()), this, SLOT(fillWindowMenu()) );
+}
+
+void KexiMainWindowImpl::fillWindowMenu()
+{
+ KexiMainWindow::fillWindowMenu();
+
+/* int i;
+ for (i=0; i < (int)m_pWindowMenu->count(); i++) {
+ if (m_pWindowMenu->text( m_pWindowMenu->idAt( i ) ) == i18n( "&MDI Mode" )) {
+// kdDebug() << m_pWindowMenu->text( m_pWindowMenu->idAt( i ) ) << endl;
+ m_pWindowMenu->removeItem( m_pWindowMenu->idAt( i ) );
+ break;
+ }
+ }*/
+
+ m_pMdiModeMenu->removeItem( m_pMdiModeMenu->idAt( 0 ) ); //hide toplevel mode
+ m_pMdiModeMenu->removeItem( m_pMdiModeMenu->idAt( 1 ) ); //hide tabbed mode
+ //update
+ if (d->mdiModeToSwitchAfterRestart != (KMdi::MdiMode)0) {
+ m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 0 ),
+ d->mdiModeToSwitchAfterRestart == KMdi::ChildframeMode );
+ m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 1 ),
+ d->mdiModeToSwitchAfterRestart == KMdi::IDEAlMode );
+ }
+
+ //insert window_next, window_previous actions:
+// const QString t = i18n("&Dock/Undock...");
+ int i = m_pWindowMenu->count()-1;
+ for (int index;; i--) {
+ index = m_pWindowMenu->idAt(i);
+ if (index==-1 || m_pWindowMenu->text(index).isNull())
+ break;
+ }
+ i++;
+ d->action_window_next->plug( m_pWindowMenu, i++ );
+ d->action_window_previous->plug( m_pWindowMenu, i++ );
+ if (!m_pDocumentViews->isEmpty())
+ m_pWindowMenu->insertSeparator( i++ );
+}
+
+void KexiMainWindowImpl::switchToIDEAlMode()
+{
+ switchToIDEAlMode(true);
+}
+
+void KexiMainWindowImpl::switchToIDEAlMode(bool showMessage)
+{
+ if (showMessage) {
+ if ((int)d->mdiModeToSwitchAfterRestart == 0 && mdiMode()==KMdi::IDEAlMode)
+ return;
+ if (d->mdiModeToSwitchAfterRestart == KMdi::IDEAlMode)
+ return;
+ if (mdiMode()==KMdi::IDEAlMode) {//current mode
+ d->mdiModeToSwitchAfterRestart = (KMdi::MdiMode)0;
+ }
+ else {
+ KMessageBox::information(this,
+ i18n("User interface mode will be switched to IDEAl at next %1 application startup.")
+ .arg(KEXI_APP_NAME));
+ //delayed
+ d->mdiModeToSwitchAfterRestart = KMdi::IDEAlMode;
+ }
+ }
+ else
+ KexiMainWindow::switchToIDEAlMode();
+}
+
+void KexiMainWindowImpl::switchToChildframeMode()
+{
+ switchToChildframeMode(true);
+}
+
+void KexiMainWindowImpl::switchToChildframeMode(bool showMessage)
+{
+ if (showMessage) {
+ if ((int)d->mdiModeToSwitchAfterRestart == 0 && mdiMode()==KMdi::ChildframeMode)
+ return;
+ if (d->mdiModeToSwitchAfterRestart == KMdi::ChildframeMode)
+ return;
+ if (mdiMode()==KMdi::ChildframeMode) {//current mode
+ d->mdiModeToSwitchAfterRestart = (KMdi::MdiMode)0;
+ }
+ else {
+ KMessageBox::information(this,
+ i18n("User interface mode will be switched to Childframe at next %1 application startup.")
+ .arg(KEXI_APP_NAME));
+ //delayed
+ d->mdiModeToSwitchAfterRestart = KMdi::ChildframeMode;
+ }
+ }
+ else
+ KexiMainWindow::switchToChildframeMode();
+}
+
+QPopupMenu* KexiMainWindowImpl::findPopupMenu(const char *popupName)
+{
+ return d->popups[popupName];
+}
+
+KActionPtrList KexiMainWindowImpl::allActions() const
+{
+ return actionCollection()->actions();
+}
+
+KexiDialogBase* KexiMainWindowImpl::currentDialog() const
+{
+ return d->curDialog;
+}
+
+void KexiMainWindowImpl::initActions()
+{
+// setupGUI(KMainWindow::Keys|KMainWindow::StatusBar|KMainWindow::Save|KMainWindow::Create);
+
+// d->actionMapper = new QSignalMapper(this, "act_map");
+// connect(d->actionMapper, SIGNAL(mapped(const QString &)), this, SLOT(slotAction(const QString &)));
+
+ // PROJECT MENU
+ KAction *action = new KAction(i18n("&New..."), "filenew", KStdAccel::shortcut(KStdAccel::New),
+ this, SLOT(slotProjectNew()), actionCollection(), "project_new");
+ action->setToolTip(i18n("Create a new project"));
+ action->setWhatsThis(i18n("Creates a new project. Currently opened project is not affected."));
+
+ action = KStdAction::open( this, SLOT( slotProjectOpen() ), actionCollection(), "project_open" );
+ action->setToolTip(i18n("Open an existing project"));
+ action->setWhatsThis(i18n("Opens an existing project. Currently opened project is not affected."));
+
+#ifdef HAVE_KNEWSTUFF
+ action = new KAction(i18n("&Download Example Databases..."), "kget", KShortcut(0),
+ this, SLOT(slotGetNewStuff()), actionCollection(), "project_download_examples");
+ action->setToolTip(i18n("Download example databases from the Internet"));
+ action->setWhatsThis(i18n("Downloads example databases from the Internet."));
+#endif
+
+// d->action_open_recent = KStdAction::openRecent( this, SLOT(slotProjectOpenRecent(const KURL&)), actionCollection(), "project_open_recent" );
+
+//#ifdef KEXI_SHOW_UNIMPLEMENTED
+#ifndef KEXI_NO_UNFINISHED
+ d->action_open_recent = new KActionMenu(i18n("Open Recent"),
+ actionCollection(), "project_open_recent");
+ connect(d->action_open_recent->popupMenu(),SIGNAL(activated(int)),
+ this,SLOT(slotProjectOpenRecent(int)));
+ connect(d->action_open_recent->popupMenu(), SIGNAL(aboutToShow()),
+ this,SLOT(slotProjectOpenRecentAboutToShow()));
+//moved down d->action_open_recent_projects_title_id =
+// d->action_open_recent->popupMenu()->insertTitle(i18n("Recently Opened Databases"));
+//moved down d->action_open_recent_connections_title_id =
+// d->action_open_recent->popupMenu()->insertTitle(i18n("Recently Connected Database Servers"));
+// d->action_open_recent->popupMenu()->insertSeparator();
+// d->action_open_recent_more_id = d->action_open_recent->popupMenu()
+// ->insertItem(i18n("&More Projects..."), this, SLOT(slotProjectOpenRecentMore()), 0, 1000);
+#else
+ d->action_open_recent = d->dummy_action;
+#endif
+
+ d->action_save = KStdAction::save(
+ this, SLOT( slotProjectSave() ), actionCollection(), "project_save" );
+// d->action_save = new KAction(i18n("&Save"), "filesave", KStdAccel::shortcut(KStdAccel::Save),
+// this, SLOT(slotProjectSave()), actionCollection(), "project_save");
+ d->action_save->setToolTip(i18n("Save object changes"));
+ d->action_save->setWhatsThis(i18n("Saves object changes from currently selected window."));
+
+#ifdef KEXI_SHOW_UNIMPLEMENTED
+ d->action_save_as = new KAction(i18n("Save &As..."), "filesaveas", 0,
+ this, SLOT(slotProjectSaveAs()), actionCollection(), "project_saveas");
+ d->action_save_as->setToolTip(i18n("Save object as"));
+ d->action_save_as->setWhatsThis(
+ i18n("Saves object changes from currently selected window under a new name (within the same project)."));
+
+ d->action_project_properties = new KAction(i18n("Project Properties"), "info", 0,
+ this, SLOT(slotProjectProperties()), actionCollection(), "project_properties");
+#else
+ d->action_save_as = d->dummy_action;
+ d->action_project_properties = d->dummy_action;
+#endif
+
+ d->action_close = new KAction(i18n("&Close Project"), "fileclose", 0,
+ this, SLOT(slotProjectClose()), actionCollection(), "project_close" );
+ d->action_close->setToolTip(i18n("Close the current project"));
+ d->action_close->setWhatsThis(i18n("Closes the current project."));
+
+ KStdAction::quit( this, SLOT(slotProjectQuit()), actionCollection(), "quit");
+
+#ifdef KEXI_SHOW_UNIMPLEMENTED
+ d->action_project_relations = new KAction(i18n("&Relationships..."), "relation", Qt::CTRL + Qt::Key_R,
+ this, SLOT(slotProjectRelations()), actionCollection(), "project_relations");
+ d->action_project_relations->setToolTip(i18n("Project relationships"));
+ d->action_project_relations->setWhatsThis(i18n("Shows project relationships."));
+
+#else
+ d->action_project_relations = d->dummy_action;
+#endif
+ d->action_tools_data_migration = new KAction(
+ i18n("&Import Database..."), "database_import", 0,
+ this, SLOT(slotToolsProjectMigration()), actionCollection(), "tools_import_project");
+ d->action_tools_data_migration->setToolTip(i18n("Import entire database as a Kexi project"));
+ d->action_tools_data_migration->setWhatsThis(i18n("Imports entire database as a Kexi project."));
+
+ d->action_tools_compact_database = new KAction(
+ i18n("&Compact Database..."), "", 0,
+ this, SLOT(slotToolsCompactDatabase()), actionCollection(), "tools_compact_database");
+ d->action_tools_compact_database->setToolTip(i18n("Compact the current database project"));
+ d->action_tools_compact_database->setWhatsThis(
+ i18n("Compacts the current database project, so it will take less space and work faster."));
+
+ if (userMode())
+ d->action_project_import_data_table = 0;
+ else {
+ d->action_project_import_data_table = new KAction(
+ i18n("Import->Table Data From File...", "Table Data From &File..."),
+ "table"/*! @todo: change to "file_import" or so*/,
+ 0, this, SLOT(slotProjectImportDataTable()), actionCollection(),
+ "project_import_data_table");
+ d->action_project_import_data_table->setToolTip(i18n("Import table data from a file"));
+ d->action_project_import_data_table->setWhatsThis(i18n("Imports table data from a file."));
+ }
+
+ d->action_project_export_data_table = new KAction(i18n("Export->Table or Query Data to File...",
+ "Table or Query Data to &File..."),
+ "table"/*! @todo: change to "file_export" or so*/,
+ 0, this, SLOT(slotProjectExportDataTable()), actionCollection(),
+ "project_export_data_table");
+ d->action_project_export_data_table->setToolTip(
+ i18n("Export data from the active table or query data to a file"));
+ d->action_project_export_data_table->setWhatsThis(
+ i18n("Exports data from the active table or query data to a file."));
+
+//TODO new KAction(i18n("From File..."), "fileopen", 0,
+//TODO this, SLOT(slotImportFile()), actionCollection(), "project_import_file");
+//TODO new KAction(i18n("From Server..."), "server", 0,
+//TODO this, SLOT(slotImportServer()), actionCollection(), "project_import_server");
+
+ d->action_project_print = KStdAction::print(this, SLOT(slotProjectPrint()),
+ actionCollection(), "project_print" );
+ d->action_project_print->setToolTip(i18n("Print data from the active table or query"));
+ d->action_project_print->setWhatsThis(i18n("Prints data from the active table or query."));
+
+ d->action_project_print_preview = KStdAction::printPreview(
+ this, SLOT(slotProjectPrintPreview()),
+ actionCollection(), "project_print_preview" );
+ d->action_project_print_preview->setToolTip(
+ i18n("Show print preview for the active table or query"));
+ d->action_project_print_preview->setWhatsThis(
+ i18n("Shows print preview for the active table or query."));
+
+ d->action_project_print_setup = new KAction(i18n("Page Set&up..."),
+ "", 0, this, SLOT(slotProjectPageSetup()), actionCollection(),
+ "project_print_setup");
+ d->action_project_print_setup->setToolTip(
+ i18n("Show page setup for printing the active table or query"));
+ d->action_project_print_setup->setWhatsThis(
+ i18n("Shows page setup for printing the active table or query."));
+
+ //EDIT MENU
+ d->action_edit_cut = createSharedAction( KStdAction::Cut, "edit_cut");
+ d->action_edit_copy = createSharedAction( KStdAction::Copy, "edit_copy");
+ d->action_edit_paste = createSharedAction( KStdAction::Paste, "edit_paste");
+
+ if (userMode())
+ d->action_edit_paste_special_data_table = 0;
+ else {
+ d->action_edit_paste_special_data_table =
+ new KAction(i18n("Paste Special->As Data &Table...", "As Data &Table..."),
+ "table", 0, this, SLOT(slotEditPasteSpecialDataTable()),
+ actionCollection(), "edit_paste_special_data_table");
+ d->action_edit_paste_special_data_table->setToolTip(
+ i18n("Paste clipboard data as a table"));
+ d->action_edit_paste_special_data_table->setWhatsThis(
+ i18n("Pastes clipboard data to a table."));
+ }
+
+ d->action_edit_copy_special_data_table =
+ new KAction(i18n("Copy Special->Table or Query Data...",
+ "Table or Query as Data Table..."),
+ "table", 0, this, SLOT(slotEditCopySpecialDataTable()),
+ actionCollection(), "edit_copy_special_data_table");
+ d->action_edit_copy_special_data_table->setToolTip(
+ i18n("Copy selected table or query data to clipboard"));
+ d->action_edit_copy_special_data_table->setWhatsThis(
+ i18n("Copies selected table or query data to clipboard."));
+
+ d->action_edit_undo = createSharedAction( KStdAction::Undo, "edit_undo");
+ d->action_edit_undo->setWhatsThis(i18n("Reverts the most recent editing action."));
+ d->action_edit_redo = createSharedAction( KStdAction::Redo, "edit_redo");
+ d->action_edit_redo->setWhatsThis(i18n("Reverts the most recent undo action."));
+
+#if 0 //old
+ d->action_edit_find = createSharedAction( KStdAction::Find, "edit_find");
+ d->action_edit_findnext = createSharedAction( KStdAction::FindNext, "edit_findnext");
+ d->action_edit_findprev = createSharedAction( KStdAction::FindPrev, "edit_findprevious");
+//! @todo d->action_edit_paste = createSharedAction( KStdAction::Replace, "edit_replace");
+#endif
+
+ d->action_edit_find = KStdAction::find(
+ this, SLOT(slotEditFind()), actionCollection(), "edit_find" );
+// d->action_edit_find = createSharedAction( KStdAction::Find, "edit_find");
+ d->action_edit_findnext = KStdAction::findNext(
+ this, SLOT(slotEditFindNext()), actionCollection(), "edit_findnext");
+ d->action_edit_findprev = KStdAction::findPrev(
+ this, SLOT(slotEditFindPrevious()), actionCollection(), "edit_findprevious");
+ d->action_edit_replace = 0;
+//! @todo d->action_edit_replace = KStdAction::replace(
+//! this, SLOT(slotEditReplace()), actionCollection(), "project_print_preview" );
+ d->action_edit_replace_all = 0;
+//! @todo d->action_edit_replace_all = new KAction( i18n("Replace All"), "", 0,
+//! this, SLOT(slotEditReplaceAll()), actionCollection(), "edit_replaceall");
+
+ d->action_edit_select_all = createSharedAction( KStdAction::SelectAll, "edit_select_all");
+
+ d->action_edit_delete = createSharedAction(i18n("&Delete"), "editdelete",
+ 0/*Qt::Key_Delete*/, "edit_delete");
+ d->action_edit_delete->setToolTip(i18n("Delete selected object"));
+ d->action_edit_delete->setWhatsThis(i18n("Deletes currently selected object."));
+
+ d->action_edit_delete_row = createSharedAction(i18n("Delete Row"), "delete_table_row",
+ Qt::CTRL+Qt::Key_Delete, "edit_delete_row");
+ d->action_edit_delete_row->setToolTip(i18n("Delete currently selected row"));
+ d->action_edit_delete_row->setWhatsThis(i18n("Deletes currently selected row."));
+
+ d->action_edit_clear_table = createSharedAction(i18n("Clear Table Contents"), "clear_table_contents",
+ 0, "edit_clear_table");
+ d->action_edit_clear_table->setToolTip(i18n("Clear table contents"));
+ d->action_edit_clear_table->setWhatsThis(i18n("Clears table contents."));
+ setActionVolatile( d->action_edit_clear_table, true );
+
+ d->action_edit_edititem = createSharedAction(i18n("Edit Item"), 0, 0, /* CONFLICT in TV: Qt::Key_F2, */
+ "edit_edititem");
+ d->action_edit_edititem->setToolTip(i18n("Edit currently selected item"));
+ d->action_edit_edititem->setWhatsThis(i18n("Edits currently selected item."));
+
+ d->action_edit_insert_empty_row = createSharedAction(i18n("&Insert Empty Row"), "insert_table_row",
+ Qt::SHIFT | Qt::CTRL | Qt::Key_Insert, "edit_insert_empty_row");
+ setActionVolatile( d->action_edit_insert_empty_row, true );
+ d->action_edit_insert_empty_row->setToolTip(i18n("Insert one empty row above"));
+ d->action_edit_insert_empty_row->setWhatsThis(i18n("Inserts one empty row above currently selected table row."));
+
+ //VIEW MENU
+ if (!userMode()) {
+ d->action_view_data_mode = new KRadioAction(i18n("&Data View"), "state_data", Qt::Key_F6,
+ this, SLOT(slotViewDataMode()), actionCollection(), "view_data_mode");
+ d->actions_for_view_modes.insert( Kexi::DataViewMode, d->action_view_data_mode );
+ d->action_view_data_mode->setExclusiveGroup("view_mode");
+ d->action_view_data_mode->setToolTip(i18n("Switch to data view"));
+ d->action_view_data_mode->setWhatsThis(i18n("Switches to data view."));
+ }
+ else
+ d->action_view_data_mode = 0;
+
+ if (!userMode()) {
+ d->action_view_design_mode = new KRadioAction(i18n("D&esign View"), "state_edit", Qt::Key_F7,
+ this, SLOT(slotViewDesignMode()), actionCollection(), "view_design_mode");
+ d->actions_for_view_modes.insert( Kexi::DesignViewMode, d->action_view_design_mode );
+ d->action_view_design_mode->setExclusiveGroup("view_mode");
+ d->action_view_design_mode->setToolTip(i18n("Switch to design view"));
+ d->action_view_design_mode->setWhatsThis(i18n("Switches to design view."));
+ }
+ else
+ d->action_view_design_mode = 0;
+
+ if (!userMode()) {
+ d->action_view_text_mode = new KRadioAction(i18n("&Text View"), "state_sql", Qt::Key_F8,
+ this, SLOT(slotViewTextMode()), actionCollection(), "view_text_mode");
+ d->actions_for_view_modes.insert( Kexi::TextViewMode, d->action_view_text_mode );
+ d->action_view_text_mode->setExclusiveGroup("view_mode");
+ d->action_view_text_mode->setToolTip(i18n("Switch to text view"));
+ d->action_view_text_mode->setWhatsThis(i18n("Switches to text view."));
+ }
+ else
+ d->action_view_text_mode = 0;
+
+ if (d->isProjectNavigatorVisible) {
+ d->action_view_nav = new KAction(i18n("Project Navigator"), "", Qt::ALT + Qt::Key_1,
+ this, SLOT(slotViewNavigator()), actionCollection(), "view_navigator");
+ d->action_view_nav->setToolTip(i18n("Go to project navigator panel"));
+ d->action_view_nav->setWhatsThis(i18n("Goes to project navigator panel."));
+ }
+ else
+ d->action_view_nav = 0;
+
+ d->action_view_mainarea = new KAction(i18n("Main Area"), "", Qt::ALT + Qt::Key_2,
+ this, SLOT(slotViewMainArea()), actionCollection(), "view_mainarea");
+ d->action_view_mainarea->setToolTip(i18n("Go to main area"));
+ d->action_view_mainarea->setWhatsThis(i18n("Goes to main area."));
+
+ if (!userMode()) {
+ d->action_view_propeditor = new KAction(i18n("Property Editor"), "", Qt::ALT + Qt::Key_3,
+ this, SLOT(slotViewPropertyEditor()), actionCollection(), "view_propeditor");
+ d->action_view_propeditor->setToolTip(i18n("Go to property editor panel"));
+ d->action_view_propeditor->setWhatsThis(i18n("Goes to property editor panel."));
+ }
+ else
+ d->action_view_propeditor = 0;
+
+ //DATA MENU
+ d->action_data_save_row = createSharedAction(i18n("&Save Row"), "button_ok",
+ Qt::SHIFT | Qt::Key_Return, "data_save_row");
+ d->action_data_save_row->setToolTip(i18n("Save changes made to the current row"));
+ d->action_data_save_row->setWhatsThis(i18n("Saves changes made to the current row."));
+//temp. disable because of problems with volatile actions setActionVolatile( d->action_data_save_row, true );
+
+ d->action_data_cancel_row_changes = createSharedAction(i18n("&Cancel Row Changes"),
+ "button_cancel", 0 , "data_cancel_row_changes");
+ d->action_data_cancel_row_changes->setToolTip(i18n("Cancel changes made to the current row"));
+ d->action_data_cancel_row_changes->setWhatsThis(i18n("Cancels changes made to the current row."));
+//temp. disable because of problems with volatile actions setActionVolatile( d->action_data_cancel_row_changes, true );
+
+ d->action_data_execute = createSharedAction(i18n("&Execute"), "player_play", 0 , "data_execute");
+ //d->action_data_execute->setToolTip(i18n("")); //TODO
+ //d->action_data_execute->setWhatsThis(i18n("")); //TODO
+
+#ifndef KEXI_NO_UNFINISHED
+ action = createSharedAction(i18n("&Filter"), "filter", 0, "data_filter");
+ setActionVolatile( action, true );
+#endif
+// action->setToolTip(i18n("")); //todo
+// action->setWhatsThis(i18n("")); //todo
+
+// setSharedMenu("data_sort");
+ action = createSharedAction(i18n("&Ascending"), "sort_az", 0, "data_sort_az");
+//temp. disable because of problems with volatile actions setActionVolatile( action, true );
+ action->setToolTip(i18n("Sort data in ascending order"));
+ action->setWhatsThis(i18n("Sorts data in ascending order (from A to Z and from 0 to 9). Data from selected column is used for sorting."));
+
+ action = createSharedAction(i18n("&Descending"), "sort_za", 0, "data_sort_za");
+//temp. disable because of problems with volatile actions setActionVolatile( action, true );
+ action->setToolTip(i18n("Sort data in descending order"));
+ action->setWhatsThis(i18n("Sorts data in descending (from Z to A and from 9 to 0). Data from selected column is used for sorting."));
+
+ // - record-navigation related actions
+ createSharedAction( KexiRecordNavigator::Actions::moveToFirstRecord(), 0, "data_go_to_first_record");
+ createSharedAction( KexiRecordNavigator::Actions::moveToPreviousRecord(), 0, "data_go_to_previous_record");
+ createSharedAction( KexiRecordNavigator::Actions::moveToNextRecord(), 0, "data_go_to_next_record");
+ createSharedAction( KexiRecordNavigator::Actions::moveToLastRecord(), 0, "data_go_to_last_record");
+ createSharedAction( KexiRecordNavigator::Actions::moveToNewRecord(), 0, "data_go_to_new_record");
+
+ //FORMAT MENU
+ d->action_format_font = createSharedAction(i18n("&Font..."), "fonts", 0, "format_font");
+ d->action_format_font->setToolTip(i18n("Change font for selected object"));
+ d->action_format_font->setWhatsThis(i18n("Changes font for selected object."));
+
+ //TOOLS MENU
+
+ //WINDOW MENU
+#ifndef Q_WS_WIN
+ //KMDI <= 3.5.1 has no shortcut here:
+ KAction *closeWindowAction = actionCollection()->action("window_close");
+ if (closeWindowAction)
+ closeWindowAction->setShortcut(KStdAccel::close());
+#endif
+
+ //additional 'Window' menu items
+ d->action_window_next = new KAction( i18n("&Next Window"), "",
+#ifdef Q_WS_WIN
+ Qt::CTRL+Qt::Key_Tab,
+#else
+ Qt::ALT+Qt::Key_Right,
+#endif
+ this, SLOT(activateNextWin()), actionCollection(), "window_next");
+ d->action_window_next->setToolTip( i18n("Next window") );
+ d->action_window_next->setWhatsThis(i18n("Switches to the next window."));
+
+ d->action_window_previous = new KAction( i18n("&Previous Window"), "",
+#ifdef Q_WS_WIN
+ Qt::CTRL+Qt::SHIFT+Qt::Key_Tab,
+#else
+ Qt::ALT+Qt::Key_Left,
+#endif
+ this, SLOT(activatePrevWin()), actionCollection(), "window_previous");
+ d->action_window_previous->setToolTip( i18n("Previous window") );
+ d->action_window_previous->setWhatsThis(i18n("Switches to the previous window."));
+
+ //SETTINGS MENU
+ setStandardToolBarMenuEnabled( true );
+ action = KStdAction::keyBindings(this, SLOT( slotConfigureKeys() ), actionCollection() );
+ action->setWhatsThis(i18n("Lets you configure shortcut keys."));
+
+#ifdef KEXI_SHOW_UNIMPLEMENTED
+ action = KStdAction::configureToolbars( this, SLOT( slotConfigureToolbars() ), actionCollection() );
+ action->setWhatsThis(i18n("Lets you configure toolbars."));
+
+ d->action_show_other = new KActionMenu(i18n("Other"),
+ actionCollection(), "options_show_other");
+#endif
+
+#ifndef KEXI_NO_CTXT_HELP
+ d->action_show_helper = new KToggleAction(i18n("Show Context Help"), "", Qt::CTRL + Qt::Key_H,
+ actionCollection(), "options_show_contexthelp");
+#if KDE_IS_VERSION(3,2,90)
+ d->action_show_helper->setCheckedState(i18n("Hide Context Help"));
+#endif
+#endif
+
+#ifdef KEXI_FORMS_SUPPORT
+ slotOptionsEnableForms(true, true);
+#else
+ slotOptionsEnableForms(false, true);
+#endif
+
+#ifdef KEXI_REPORTS_SUPPORT
+ Kexi::tempShowReports() = true;
+#else
+ Kexi::tempShowReports() = false;
+#endif
+
+#ifdef KEXI_MACROS_SUPPORT
+ Kexi::tempShowMacros() = true;
+#else
+ Kexi::tempShowMacros() = false;
+#endif
+
+#ifdef KEXI_SCRIPTS_SUPPORT
+ Kexi::tempShowScripts() = true;
+#else
+ Kexi::tempShowScripts() = false;
+#endif
+
+#ifdef KEXI_SHOW_UNIMPLEMENTED
+ d->action_configure = KStdAction::preferences(this, SLOT(slotShowSettings()), actionCollection());
+ action->setWhatsThis(i18n("Lets you configure Kexi."));
+#endif
+
+ //HELP MENU
+#if 0//js: todo reenable later
+ KStdAction::tipOfDay( this, SLOT( slotTipOfTheDayAction() ), actionCollection() )
+ ->setWhatsThis(i18n("This shows useful tips on the use of this application."));
+#endif
+#if 0 //we don't have a time for updating info text for each new version
+ new KAction(i18n("Important Information"), "messagebox_info", 0,
+ this, SLOT(slotImportantInfo()), actionCollection(), "help_show_important_info");
+#endif
+//TODO: UNCOMMENT TO REMOVE MDI MODES SETTING m_pMdiModeMenu->hide();
+
+#ifndef KEXI_NO_FEEDBACK_AGENT
+#ifdef FEEDBACK_CLASS
+ new KAction(i18n("Give Feedback..."), "messagebox_info", 0,
+ this, SLOT(slotStartFeedbackAgent()), actionCollection(), "help_start_feedback_agent");
+#endif
+#endif
+// KAction *actionSettings = new KAction(i18n("Configure Kexi..."), "configure", 0,
+// actionCollection(), "kexi_settings");
+// actionSettings->setWhatsThis(i18n("Lets you configure Kexi."));
+// connect(actionSettings, SIGNAL(activated()), this, SLOT(slotShowSettings()));
+
+ // -- add a few missing tooltips (usable especially in Form's "Assign action" dialog)
+ if ((action = actionCollection()->action("window_close")))
+ action->setToolTip(i18n("Close the current window"));
+
+ // ----- declare action categories, so form's "assign action to button"
+ // (and macros in the future) will be able to recognize category
+ // of actions and filter them -----------------------------------
+//! @todo shouldn't we move this to core?
+ Kexi::ActionCategories *acat = Kexi::actionCategories();
+ acat->addAction("data_execute", Kexi::PartItemActionCategory);
+
+ //! @todo unused for now
+ acat->addWindowAction("data_filter",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addWindowAction("data_save_row",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addWindowAction("data_cancel_row_changes",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addWindowAction("delete_table_row",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ //! @todo support this in KexiPart::FormObjectType as well
+ acat->addWindowAction("data_sort_az",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ //! @todo support this in KexiPart::FormObjectType as well
+ acat->addWindowAction("data_sort_za",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ //! @todo support this in KexiPart::FormObjectType as well
+ acat->addWindowAction("edit_clear_table",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ //! @todo support this in KexiPart::FormObjectType as well
+ acat->addWindowAction("edit_copy_special_data_table",
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ // GlobalActions, etc.
+ acat->addAction("edit_copy", Kexi::GlobalActionCategory|Kexi::PartItemActionCategory);
+
+ acat->addAction("edit_cut", Kexi::GlobalActionCategory|Kexi::PartItemActionCategory);
+
+ acat->addAction("edit_paste", Kexi::GlobalActionCategory|Kexi::PartItemActionCategory);
+
+ acat->addAction("edit_delete", Kexi::GlobalActionCategory|Kexi::PartItemActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addAction("edit_delete_row", Kexi::GlobalActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addAction("edit_edititem", Kexi::PartItemActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ acat->addAction("edit_find", Kexi::GlobalActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addAction("edit_findnext", Kexi::GlobalActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addAction("edit_findprevious", Kexi::GlobalActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addAction("edit_replace", Kexi::GlobalActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ acat->addAction("edit_paste_special_data_table", Kexi::GlobalActionCategory);
+
+ acat->addAction("help_about_app", Kexi::GlobalActionCategory);
+
+ acat->addAction("help_about_kde", Kexi::GlobalActionCategory);
+
+ acat->addAction("help_contents", Kexi::GlobalActionCategory);
+
+ acat->addAction("help_report_bug", Kexi::GlobalActionCategory);
+
+ acat->addAction("help_whats_this", Kexi::GlobalActionCategory);
+
+ acat->addAction("options_configure_keybinding", Kexi::GlobalActionCategory);
+
+ acat->addAction("project_close", Kexi::GlobalActionCategory);
+
+ //! @todo support this in FormObjectType as well
+ acat->addAction("project_export_data_table", Kexi::GlobalActionCategory|Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ acat->addAction("project_import_data_table", Kexi::GlobalActionCategory);
+
+ acat->addAction("project_new", Kexi::GlobalActionCategory);
+
+ acat->addAction("project_open", Kexi::GlobalActionCategory);
+
+ //! @todo support this in FormObjectType, ReportObjectType as well as others
+ acat->addAction("project_print", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ //! @todo support this in FormObjectType, ReportObjectType as well as others
+ acat->addAction("project_print_preview", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ //! @todo support this in FormObjectType, ReportObjectType as well as others
+ acat->addAction("project_print_setup", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType);
+
+ acat->addAction("quit", Kexi::GlobalActionCategory);
+
+ acat->addAction("tools_compact_database", Kexi::GlobalActionCategory);
+
+ acat->addAction("tools_import_project", Kexi::GlobalActionCategory);
+
+ acat->addAction("view_data_mode", Kexi::GlobalActionCategory);
+
+ acat->addAction("view_design_mode", Kexi::GlobalActionCategory);
+
+ acat->addAction("view_text_mode", Kexi::GlobalActionCategory);
+
+ acat->addAction("view_mainarea", Kexi::GlobalActionCategory);
+
+ acat->addAction("view_navigator", Kexi::GlobalActionCategory);
+
+ acat->addAction("view_propeditor", Kexi::GlobalActionCategory);
+
+ acat->addAction("window_close", Kexi::GlobalActionCategory | Kexi::WindowActionCategory);
+ acat->setAllObjectTypesSupported("window_close", true);
+
+ acat->addAction("window_next", Kexi::GlobalActionCategory);
+
+ acat->addAction("window_previous", Kexi::GlobalActionCategory);
+
+ //skipped - design view only
+ acat->addAction("format_font", Kexi::NoActionCategory);
+ acat->addAction("project_save", Kexi::NoActionCategory);
+ acat->addAction("edit_insert_empty_row", Kexi::NoActionCategory);
+ //! @todo support this in KexiPart::TableObjectType, KexiPart::QueryObjectType later
+ acat->addAction("edit_select_all", Kexi::NoActionCategory);
+ //! @todo support this in KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType later
+ acat->addAction("edit_redo", Kexi::NoActionCategory);
+ //! @todo support this in KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType later
+ acat->addAction("edit_undo", Kexi::NoActionCategory);
+
+ //record-navigation related actions
+ acat->addAction("data_go_to_first_record", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+ acat->addAction("data_go_to_previous_record", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+ acat->addAction("data_go_to_next_record", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+ acat->addAction("data_go_to_last_record", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+ acat->addAction("data_go_to_new_record", Kexi::WindowActionCategory,
+ KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType);
+
+ //skipped - internal:
+ acat->addAction("tablepart_create", Kexi::NoActionCategory);
+ acat->addAction("querypart_create", Kexi::NoActionCategory);
+ acat->addAction("formpart_create", Kexi::NoActionCategory);
+ acat->addAction("reportpart_create", Kexi::NoActionCategory);
+ acat->addAction("macropart_create", Kexi::NoActionCategory);
+ acat->addAction("scriptpart_create", Kexi::NoActionCategory);
+}
+
+void KexiMainWindowImpl::invalidateActions()
+{
+ invalidateProjectWideActions();
+ invalidateSharedActions();
+}
+
+void KexiMainWindowImpl::invalidateSharedActions(QObject *o)
+{
+ //TODO: enabling is more complex...
+/* d->action_edit_cut->setEnabled(true);
+ d->action_edit_copy->setEnabled(true);
+ d->action_edit_paste->setEnabled(true);*/
+
+ if (!o)
+ o = focusWindow();
+ KexiSharedActionHost::invalidateSharedActions(o);
+}
+
+void KexiMainWindowImpl::invalidateSharedActions()
+{
+ invalidateSharedActions(0);
+}
+
+// unused, I think
+void KexiMainWindowImpl::invalidateSharedActionsLater()
+{
+ QTimer::singleShot(1, this, SLOT(invalidateSharedActions()));
+}
+
+void KexiMainWindowImpl::invalidateProjectWideActions()
+{
+// stateChanged("project_opened",d->prj ? StateNoReverse : StateReverse);
+
+ const bool have_dialog = d->curDialog;
+ const bool dialog_dirty = d->curDialog && d->curDialog->dirty();
+ const bool readOnly = d->prj && d->prj->dbConnection() && d->prj->dbConnection()->isReadOnly();
+
+ //PROJECT MENU
+ d->action_save->setEnabled(have_dialog && dialog_dirty && !readOnly);
+ d->action_save_as->setEnabled(have_dialog && !readOnly);
+ d->action_project_properties->setEnabled(d->prj);
+ d->action_close->setEnabled(d->prj);
+ d->action_project_relations->setEnabled(d->prj);
+ if (d->action_project_import_data_table)
+ d->action_project_import_data_table->setEnabled(d->prj && !readOnly);
+ d->action_project_export_data_table->setEnabled(
+ d->curDialog && d->curDialog->part()->info()->isDataExportSupported()
+ && !d->curDialog->neverSaved() );
+
+ const bool printingActionsEnabled =
+ d->curDialog && d->curDialog->part()->info()->isPrintingSupported()
+ && !d->curDialog->neverSaved();
+ d->action_project_print->setEnabled( printingActionsEnabled );
+ d->action_project_print_preview->setEnabled( printingActionsEnabled );
+ d->action_project_print_setup->setEnabled( printingActionsEnabled );
+
+ //EDIT MENU
+
+ if (d->action_edit_paste_special_data_table)
+ d->action_edit_paste_special_data_table->setEnabled(d->prj && !readOnly);
+
+//! @todo "copy special" is currently enabled only for data view mode;
+//! what about allowing it to enable in design view for "kexi/table" ?
+ if (d->curDialog && d->curDialog->currentViewMode()==Kexi::DataViewMode) {
+ KexiPart::Info *activePartInfo = d->curDialog->part()->info();
+ d->action_edit_copy_special_data_table->setEnabled(
+ activePartInfo ? activePartInfo->isDataExportSupported() : false );
+ }
+ else
+ d->action_edit_copy_special_data_table->setEnabled( false );
+
+ //VIEW MENU
+ if (d->action_view_nav)
+ d->action_view_nav->setEnabled(d->prj);
+ d->action_view_mainarea->setEnabled(d->prj);
+ if (d->action_view_propeditor)
+ d->action_view_propeditor->setEnabled(d->prj);
+ if (d->action_view_data_mode) {
+ d->action_view_data_mode->setEnabled( have_dialog && d->curDialog->supportsViewMode(Kexi::DataViewMode) );
+ if (!d->action_view_data_mode->isEnabled())
+ d->action_view_data_mode->setChecked(false);
+ }
+ if (d->action_view_design_mode) {
+ d->action_view_design_mode->setEnabled( have_dialog && d->curDialog->supportsViewMode(Kexi::DesignViewMode) );
+ if (!d->action_view_design_mode->isEnabled())
+ d->action_view_design_mode->setChecked(false);
+ }
+ if (d->action_view_text_mode) {
+ d->action_view_text_mode->setEnabled( have_dialog && d->curDialog->supportsViewMode(Kexi::TextViewMode) );
+ if (!d->action_view_text_mode->isEnabled())
+ d->action_view_text_mode->setChecked(false);
+ }
+#ifndef KEXI_NO_CTXT_HELP
+ d->action_show_helper->setEnabled(d->prj);
+#endif
+
+ //CREATE MENU
+ if (d->createMenu)
+ d->createMenu->setEnabled(d->prj);
+
+ // DATA MENU
+ //d->action_data_execute->setEnabled( d->curDialog && d->curDialog->part()->info()->isExecuteSupported() );
+
+ //TOOLS MENU
+ // "compact db" supported if there's no db or the current db supports compacting and is opened r/w:
+ d->action_tools_compact_database->setEnabled(
+ !d->prj || !readOnly && d->prj && d->prj->dbConnection()
+ && (d->prj->dbConnection()->driver()->features() & KexiDB::Driver::CompactingDatabaseSupported) );
+
+ //WINDOW MENU
+ if (d->action_window_next) {
+ d->action_window_next->setEnabled(!m_pDocumentViews->isEmpty());
+ d->action_window_previous->setEnabled(!m_pDocumentViews->isEmpty());
+ }
+
+ //DOCKS
+ if (d->nav)
+ d->nav->setEnabled(d->prj);
+ if (d->propEditor)
+ d->propEditorTabWidget->setEnabled(d->prj);
+}
+
+void KexiMainWindowImpl::invalidateViewModeActions()
+{
+ if (d->curDialog) {
+ //update toggle action
+ if (d->curDialog->currentViewMode()==Kexi::DataViewMode) {
+ if (d->action_view_data_mode)
+ d->action_view_data_mode->setChecked( true );
+ }
+ else if (d->curDialog->currentViewMode()==Kexi::DesignViewMode) {
+ if (d->action_view_design_mode)
+ d->action_view_design_mode->setChecked( true );
+ }
+ else if (d->curDialog->currentViewMode()==Kexi::TextViewMode) {
+ if (d->action_view_text_mode)
+ d->action_view_text_mode->setChecked( true );
+ }
+ }
+}
+
+tristate KexiMainWindowImpl::startup()
+{
+ switch (Kexi::startupHandler().action()) {
+ case KexiStartupHandler::CreateBlankProject:
+ if (d->propEditor)
+ makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
+ return createBlankProject();
+ case KexiStartupHandler::CreateFromTemplate:
+ return createProjectFromTemplate(*Kexi::startupHandler().projectData());
+ case KexiStartupHandler::OpenProject:
+ return openProject(*Kexi::startupHandler().projectData());
+ case KexiStartupHandler::ImportProject:
+ return showProjectMigrationWizard(
+ Kexi::startupHandler().importActionData().mimeType,
+ Kexi::startupHandler().importActionData().fileName
+ );
+ default:;
+ if (d->propEditor)
+ makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
+ }
+ return true;
+}
+
+static QString internalReason(KexiDB::Object *obj)
+{
+ const QString &s = obj->errorMsg();
+ if (s.isEmpty())
+ return s;
+ return QString("<br>(%1) ").arg(i18n("reason:")+" <i>"+s+"</i>");
+}
+
+tristate KexiMainWindowImpl::openProject(const KexiProjectData& projectData)
+{
+ KexiProjectData *newProjectData = new KexiProjectData(projectData);
+// if (userMode()) {
+ //TODO: maybe also auto allow to open objects...
+// return initUserModeMode(newProjectData);
+// }
+ createKexiProject( newProjectData );
+ if (!newProjectData->connectionData()->savePassword
+ && newProjectData->connectionData()->password.isEmpty()
+ && newProjectData->connectionData()->fileName().isEmpty() //! @todo temp.: change this if there are file-based drivers requiring a password
+ )
+ {
+ //ask for password
+ KexiDBPasswordDialog pwdDlg(this, *newProjectData->connectionData(),
+ false /*!showDetailsButton*/);
+ if (QDialog::Accepted!=pwdDlg.exec()) {
+ delete d->prj;
+ d->prj = 0;
+ return cancelled;
+ }
+ }
+ bool incompatibleWithKexi;
+ tristate res = d->prj->open(incompatibleWithKexi);
+ if (~res) {
+ delete d->prj;
+ d->prj = 0;
+ return cancelled;
+ }
+ else if (!res) {
+ delete d->prj;
+ d->prj = 0;
+ if (incompatibleWithKexi) {
+ if (KMessageBox::Yes == KMessageBox::questionYesNo(this,
+ i18n("<qt>Database project %1 does not appear to have been created using Kexi.<br><br>"
+ "Do you want to import it as a new Kexi project?</qt>").arg(projectData.infoString()),
+ 0, KGuiItem(i18n("Import Database", "&Import..."), "database_import"),
+ KStdGuiItem::quit()))
+ {
+ const bool anotherProjectAlreadyOpened = d->prj;
+ tristate res = showProjectMigrationWizard("application/x-kexi-connectiondata",
+ projectData.databaseName(), projectData.constConnectionData());
+
+ if (!anotherProjectAlreadyOpened) //the project could have been opened within this instance
+ return res;
+
+ //always return cancelled because even if migration succeeded, new Kexi instance
+ //will be started if user wanted to open the imported db
+ return cancelled;
+ }
+ return cancelled;
+ }
+ return false;
+ }
+ initNavigator();
+ Kexi::recentProjects().addProjectData( newProjectData );
+ updateReadOnlyState();
+ invalidateActions();
+// d->disableErrorMessages = true;
+ enableMessages( false );
+
+ QTimer::singleShot(1, this, SLOT(slotAutoOpenObjectsLater()));
+ return true;
+}
+
+tristate KexiMainWindowImpl::createProjectFromTemplate(const KexiProjectData& projectData)
+{
+ QStringList mimetypes;
+ mimetypes.append( KexiDB::Driver::defaultFileBasedDriverMimeType() );
+ QString fname;
+ const QString startDir(":OpenExistingOrCreateNewProject"/*as in KexiNewProjectWizard*/);
+ const QString caption( i18n("Select New Project's Location") );
+
+ while (true) {
+#ifdef Q_WS_WIN
+ //! @todo remove
+ QString recentDir = KGlobalSettings::documentPath();
+ if (fname.isEmpty() && !projectData.constConnectionData()->dbFileName().isEmpty()) //propose filename from db template name
+ fname = KFileDialog::getStartURL(startDir, recentDir).path()
+ + '/' + projectData.constConnectionData()->dbFileName();
+ fname = QFileDialog::getSaveFileName(
+ KFileDialog::getStartURL(fname.isEmpty() ? startDir : fname, recentDir).path(),
+ KexiUtils::fileDialogFilterStrings(mimetypes, false),
+ this, "CreateProjectFromTemplate", caption);
+ if ( !fname.isEmpty() ) {
+ //save last visited path
+ KURL url;
+ url.setPath( fname );
+ if (url.isLocalFile())
+ KRecentDirs::add(startDir, url.directory());
+ }
+#else
+ Q_UNUSED(projectData);
+ if (fname.isEmpty() &&
+ !projectData.constConnectionData()->dbFileName().isEmpty())
+ {
+ //propose filename from db template name
+ fname = projectData.constConnectionData()->dbFileName();
+ }
+ const bool specialDir = fname.isEmpty();
+ kdDebug() << fname << "............." << endl;
+ KFileDialog dlg( specialDir ? startDir : QString::null,
+ mimetypes.join(" "), this, "filedialog", true);
+ if ( !specialDir )
+ dlg.setSelection( fname ); // may also be a filename
+ dlg.setOperationMode( KFileDialog::Saving );
+ dlg.setCaption( caption );
+ dlg.exec();
+ fname = dlg.selectedFile();
+ if (!fname.isEmpty())
+ KRecentDocument::add(fname);
+// fname = KFileDialog::getSaveFileName(fname.isEmpty() ? startDir : fname,
+ // mimetypes.join(" "), this, caption);
+#endif
+ if ( fname.isEmpty() )
+ return cancelled;
+ if (KexiStartupFileDialog::askForOverwriting(fname, this))
+ break;
+ }
+
+ if (KexiUtils::CopySuccess != KexiUtils::copyFile(
+ projectData.constConnectionData()->fileName(), fname ))
+ {
+ return false;
+ }
+
+ return openProject(fname, 0, QString::null, projectData.autoopenObjects/*copy*/);
+}
+
+void KexiMainWindowImpl::updateReadOnlyState()
+{
+ const bool readOnly = d->prj && d->prj->dbConnection() && d->prj->dbConnection()->isReadOnly();
+ d->statusBar->setReadOnlyFlag( readOnly );
+ if (d->nav)
+ d->nav->setReadOnly(readOnly);
+ // update "insert ....." actions for every part
+ KActionCollection *ac = actionCollection();
+ for (KexiPart::PartInfoListIterator it(*Kexi::partManager().partInfoList()); it.current(); ++it) {
+ KAction *a = ac->action( KexiPart::nameForCreateAction( *it.current() ) );
+ if (a)
+ a->setEnabled(!readOnly);
+ }
+}
+
+void KexiMainWindowImpl::slotAutoOpenObjectsLater()
+{
+ QString not_found_msg;
+ bool openingCancelled;
+ //ok, now open "autoopen: objects
+ if (d->prj) {
+ for (QValueList<KexiProjectData::ObjectInfo>::ConstIterator it =
+ d->prj->data()->autoopenObjects.constBegin();
+ it != d->prj->data()->autoopenObjects.constEnd(); ++it )
+ {
+ KexiProjectData::ObjectInfo info = *it;
+ KexiPart::Info *i = Kexi::partManager().infoForMimeType(
+ QCString("kexi/")+info["type"].lower().latin1() );
+ if (!i) {
+ not_found_msg += "<li>";
+ if (!info["name"].isEmpty())
+ not_found_msg += (QString("\"") + info["name"] + "\" - ");
+ if (info["action"]=="new")
+ not_found_msg += i18n("cannot create object - unknown object type \"%1\"")
+ .arg(info["type"]);
+ else
+ not_found_msg += i18n("unknown object type \"%1\"").arg(info["type"]);
+ not_found_msg += internalReason(&Kexi::partManager())+"<br></li>";
+ continue;
+ }
+ // * NEW
+ if (info["action"]=="new") {
+ if (!newObject( i, openingCancelled) && !openingCancelled) {
+ not_found_msg += "<li>";
+ not_found_msg += (i18n("cannot create object of type \"%1\"").arg(info["type"])+
+ internalReason(d->prj)+"<br></li>");
+ }
+ else
+ d->wasAutoOpen = true;
+ continue;
+ }
+
+ KexiPart::Item *item = d->prj->item(i, info["name"]);
+
+ if (!item) {
+ QString taskName;
+ if (info["action"]=="print-preview")
+ taskName = i18n("making print preview for");
+ else if (info["action"]=="print")
+ taskName = i18n("printing");
+ else if (info["action"]=="execute")
+ taskName = i18n("\"executing object\" action", "executing");
+ else
+ taskName = i18n("opening");
+
+ not_found_msg += (QString("<li>")+ taskName + " \"" + info["name"] + "\" - ");
+ if ("table"==info["type"].lower())
+ not_found_msg += i18n("table not found");
+ else if ("query"==info["type"].lower())
+ not_found_msg += i18n("query not found");
+ else if ("macro"==info["type"].lower())
+ not_found_msg += i18n("macro not found");
+ else if ("script"==info["type"].lower())
+ not_found_msg += i18n("script not found");
+ else
+ not_found_msg += i18n("object not found");
+ not_found_msg += (internalReason(d->prj)+"<br></li>");
+ continue;
+ }
+ // * EXECUTE, PRINT, PRINT PREVIEW
+ if (info["action"]=="execute") {
+ tristate res = executeItem(item);
+ if (false == res) {
+ not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot execute object")+
+ internalReason(d->prj)+"<br></li>" );
+ }
+ continue;
+ }
+ else if (info["action"]=="print") {
+ tristate res = printItem(item);
+ if (false == res) {
+ not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot print object")+
+ internalReason(d->prj)+"<br></li>" );
+ }
+ continue;
+ }
+ else if (info["action"]=="print-preview") {
+ tristate res = printPreviewForItem(item);
+ if (false == res) {
+ not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot make print preview of object")+
+ internalReason(d->prj)+"<br></li>" );
+ }
+ continue;
+ }
+
+ int viewMode;
+ if (info["action"]=="open")
+ viewMode = Kexi::DataViewMode;
+ else if (info["action"]=="design")
+ viewMode = Kexi::DesignViewMode;
+ else if (info["action"]=="edittext")
+ viewMode = Kexi::TextViewMode;
+ else
+ continue; //sanity
+
+ QString openObjectMessage;
+ if (!openObject(item, viewMode, openingCancelled, 0, &openObjectMessage)
+ && (!openingCancelled || !openObjectMessage.isEmpty()))
+ {
+ not_found_msg += (QString("<li>\"")+ info["name"] + "\" - ");
+ if (openObjectMessage.isEmpty())
+ not_found_msg += i18n("cannot open object");
+ else
+ not_found_msg += openObjectMessage;
+ not_found_msg += internalReason(d->prj) + "<br></li>";
+ continue;
+ }
+ else {
+ d->wasAutoOpen = true;
+ }
+ }
+ }
+ enableMessages( true );
+// d->disableErrorMessages = false;
+
+ if (!not_found_msg.isEmpty())
+ showErrorMessage(i18n("You have requested selected objects to be automatically opened "
+ "or processed on startup. Several objects cannot be opened or processed."),
+ QString("<ul>%1</ul>").arg(not_found_msg) );
+
+ d->updatePropEditorVisibility(d->curDialog ? d->curDialog->currentViewMode() : 0);
+#if defined(KDOCKWIDGET_P)
+ if (d->propEditor) {
+ KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ if(ds)
+ ds->setSeparatorPosInPercent(d->config->readNumEntry("RightDockPosition", 80/* % */));
+ }
+#endif
+
+ updateAppCaption();
+
+// d->navToolWindow->wrapperWidget()->setFixedWidth(200);
+//js TODO: make visible FOR OTHER MODES if needed
+ if (mdiMode()==KMdi::ChildframeMode || mdiMode()==KMdi::TabPageMode) {
+ //make docks visible again
+ if (!d->navToolWindow->wrapperWidget()->isVisible())
+ static_cast<KDockWidget*>(d->navToolWindow->wrapperWidget())->makeDockVisible();
+// if (!d->propEditorToolWindow->wrapperWidget()->isVisible())
+// static_cast<KDockWidget*>(d->propEditorToolWindow->wrapperWidget())->makeDockVisible();
+ }
+
+ // if (!d->prj->data()->autoopenObjects.isEmpty())
+ d->restoreNavigatorWidth();
+
+#ifndef PROPEDITOR_VISIBILITY_CHANGES
+// KDockWidget *dw = (KDockWidget *)d->nav->parentWidget();
+// KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+// const int pos = ds->separatorPos();
+
+ //if (!d->curDialog || d->curDialog->currentViewMode()==Kexi::DataViewMode)
+// d->propEditorToolWindow->hide();
+
+// ds->setSeparatorPos( pos, true );
+#endif
+ if (d->nav) {
+ d->nav->updateGeometry();
+ }
+ qApp->processEvents();
+ emit projectOpened();
+}
+
+tristate KexiMainWindowImpl::closeProject()
+{
+#ifndef KEXI_NO_PENDING_DIALOGS
+ if (d->pendingDialogsExist()) {
+ kdDebug() << "KexiMainWindowImpl::closeProject() pendingDialogsExist..." << endl;
+ d->actionToExecuteWhenPendingJobsAreFinished = Private::CloseProjectAction;
+ return cancelled;
+ }
+#endif
+
+ //only save nav. visibility setting is project is opened
+ d->saveSettingsForShowProjectNavigator = d->prj && d->isProjectNavigatorVisible;
+
+ if (!d->prj)
+ return true;
+
+ {
+ // make sure the project can be closed
+ bool cancel = false;
+ emit acceptProjectClosingRequested(cancel);
+ if (cancel)
+ return cancelled;
+ }
+
+ d->dialogExistedBeforeCloseProject = !d->curDialog.isNull();
+
+#if defined(KDOCKWIDGET_P)
+ //remember docks position - will be used on storeSettings()
+ if (d->propEditor) {
+ KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ if (ds)
+ d->propEditorDockSeparatorPos = ds->separatorPosInPercent();
+ }
+ if (d->nav) {
+// makeDockInvisible( manager()->findWidgetParentDock(d->propEditor) );
+
+ if (d->propEditor) {
+ if (d->openedDialogsCount() == 0)
+ makeWidgetDockVisible(d->propEditorTabWidget);
+ KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ if(ds)
+ ds->setSeparatorPosInPercent(80);
+ }
+
+ KDockWidget *dw = (KDockWidget *)d->nav->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ int dwWidth = dw->width();
+ if (ds) {
+ if (d->openedDialogsCount()!=0 && d->propEditorTabWidget && d->propEditorTabWidget->isVisible())
+ d->navDockSeparatorPos = ds->separatorPosInPercent();
+ else
+ d->navDockSeparatorPos = (100 * dwWidth) / width();
+
+// int navDockSeparatorPosWithAutoOpen = (100 * dw->width()) / width() + 4;
+// d->navDockSeparatorPos = (100 * dw->width()) / width() + 1;
+ }
+ }
+#endif
+
+ //close each window, optionally asking if user wants to close (if data changed)
+ while (!d->curDialog.isNull()) {
+ tristate res = closeDialog( d->curDialog );
+ if (!res || ~res)
+ return res;
+ }
+
+ // now we will close for sure
+ emit beforeProjectClosing();
+
+ if (!d->prj->closeConnection())
+ return false;
+
+ if(d->nav)
+ {
+ d->navWasVisibleBeforeProjectClosing = manager()->findWidgetParentDock(d->nav)->isVisible();
+ d->nav->clear();
+#if 0 //do not confuse users
+ d->navToolWindow->hide();
+#endif
+ }
+
+ if (d->propEditor)
+ makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
+
+// if(d->propEditorToolWindow)
+ // d->propEditorToolWindow->hide();
+
+ d->clearDialogs(); //sanity!
+ delete d->prj;
+ d->prj=0;
+
+// Kexi::partManager().unloadAllParts();
+
+ updateReadOnlyState();
+ invalidateActions();
+// if (!userMode())
+ updateAppCaption();
+
+ emit projectClosed();
+ return true;
+}
+
+void KexiMainWindowImpl::initContextHelp() {
+#ifndef KEXI_NO_CTXT_HELP
+ d->ctxHelp=new KexiContextHelp(this,this);
+/*todo
+ d->ctxHelp->setContextHelp(i18n("Welcome"),i18n("The <B>KEXI team</B> wishes you a lot of productive work, "
+ "with this product. <BR><HR><BR>If you have found a <B>bug</B> or have a <B>feature</B> request, please don't "
+ "hesitate to report it at our <A href=\"http://www.kexi-project.org/cgi-bin/bug.pl\"> issue "
+ "tracking system </A>.<BR><HR><BR>If you would like to <B>join</B> our effort, the <B>development</B> documentation "
+ "at <A href=\"http://www.kexi-project.org\">www.kexi-project.org</A> is a good starting point."),0);
+*/
+ addToolWindow(d->ctxHelp,KDockWidget::DockBottom | KDockWidget::DockLeft,getMainDockWidget(),20);
+#endif
+}
+
+void KexiMainWindowImpl::initNavigator()
+{
+ if (!d->isProjectNavigatorVisible)
+ return;
+
+ if(!d->nav)
+ {
+ d->nav = new KexiBrowser(this, this);
+ d->nav->installEventFilter(this);
+ d->navToolWindow = addToolWindow(d->nav, KDockWidget::DockLeft, getMainDockWidget(), 20/*, lv, 35, "2"*/);
+// d->navToolWindow->hide();
+
+ connect(d->nav,SIGNAL(openItem(KexiPart::Item*,int)),this,SLOT(openObject(KexiPart::Item*,int)));
+ connect(d->nav,SIGNAL(openOrActivateItem(KexiPart::Item*,int)),
+ this,SLOT(openObjectFromNavigator(KexiPart::Item*,int)));
+ connect(d->nav,SIGNAL(newItem( KexiPart::Info* )),
+ this,SLOT(newObject(KexiPart::Info*)));
+ connect(d->nav,SIGNAL(removeItem(KexiPart::Item*)),
+ this,SLOT(removeObject(KexiPart::Item*)));
+ connect(d->nav,SIGNAL(renameItem(KexiPart::Item*,const QString&, bool&)),
+ this,SLOT(renameObject(KexiPart::Item*,const QString&, bool&)));
+ connect(d->nav,SIGNAL(executeItem(KexiPart::Item*)),
+ this,SLOT(executeItem(KexiPart::Item*)));
+ connect(d->nav,SIGNAL(exportItemAsDataTable(KexiPart::Item*)),
+ this,SLOT(exportItemAsDataTable(KexiPart::Item*)));
+ connect(d->nav,SIGNAL(printItem( KexiPart::Item* )),
+ this,SLOT(printItem(KexiPart::Item*)));
+ connect(d->nav,SIGNAL(pageSetupForItem( KexiPart::Item*)),
+ this,SLOT(showPageSetupForItem(KexiPart::Item*)));
+ if (d->prj) {//connect to the project
+ connect(d->prj, SIGNAL(itemRemoved(const KexiPart::Item&)),
+ d->nav, SLOT(slotRemoveItem(const KexiPart::Item&)));
+ }
+ connect(d->nav,SIGNAL(selectionChanged(KexiPart::Item*)),
+ this,SLOT(slotPartItemSelectedInNavigator(KexiPart::Item*)));
+
+// d->restoreNavigatorWidth();
+ }
+ if(d->prj->isConnected()) {
+ QString partManagerErrorMessages;
+ d->nav->setProject( d->prj, QString::null/*all mimetypes*/, &partManagerErrorMessages );
+ if (!partManagerErrorMessages.isEmpty()) {
+ showWarningContinueMessage(partManagerErrorMessages, QString::null,
+ "dontShowWarningsRelatedToPluginsLoading");
+ }
+ }
+ connect(d->prj, SIGNAL(newItemStored(KexiPart::Item&)), d->nav, SLOT(addItem(KexiPart::Item&)));
+ d->nav->setFocus();
+
+ if (d->forceShowProjectNavigatorOnCreation) {
+ slotViewNavigator();
+ d->forceShowProjectNavigatorOnCreation = false;
+ }
+ else if (d->forceHideProjectNavigatorOnCreation) {
+ d->navToolWindow->hide();
+// makeDockInvisible( manager()->findWidgetParentDock(d->nav) );
+ d->forceHideProjectNavigatorOnCreation = false;
+ }
+
+ invalidateActions();
+}
+
+void KexiMainWindowImpl::slotLastActions()
+{
+#if defined(KDOCKWIDGET_P)
+ if (mdiMode()==KMdi::ChildframeMode || mdiMode()==KMdi::TabPageMode) {
+// KDockWidget *dw = (KDockWidget *)d->propEditor->parentWidget();
+ //KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+// Q_UNUSED(ds);
+//1 ds->resize(ds->width()*3, ds->height());
+//1 ds->setSeparatorPos(30, true);
+//1 ds->setForcedFixedWidth( dw, 200 );
+ }
+#endif
+#ifdef Q_WS_WIN
+ showMaximized();//js: workaround for not yet completed layout settings storage on win32
+#endif
+}
+
+void KexiMainWindowImpl::initPropertyEditor()
+{
+ if (!d->propEditor) {
+//TODO: FIX LAYOUT PROBLEMS
+ d->propEditorTabWidget = new KTabWidget(this);
+ d->propEditorTabWidget->hide();
+ d->propEditor = new KexiPropertyEditorView(this, d->propEditorTabWidget);
+ d->propEditorTabWidget->setCaption(d->propEditor->caption());
+ d->propEditorTabWidget->addTab(d->propEditor, i18n("Properties"));
+ d->propEditor->installEventFilter(this);
+ d->propEditorToolWindow = addToolWindow(d->propEditorTabWidget,
+ KDockWidget::DockRight, getMainDockWidget(), 20);
+
+ d->config->setGroup("PropertyEditor");
+ int size = d->config->readNumEntry("FontSize", -1);
+ QFont f( Kexi::smallFont() );
+ if (size>0)
+ f.setPixelSize( size );
+ d->propEditorTabWidget->setFont(f);
+
+ if (mdiMode()==KMdi::ChildframeMode || mdiMode()==KMdi::TabPageMode) {
+ KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
+ #if defined(KDOCKWIDGET_P)
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+// ds->setKeepSize(true);
+ makeWidgetDockVisible(d->propEditorTabWidget);
+ // ds->show();
+ // ds->resize(400, ds->height());
+ // ds->setSeparatorPos(400, true);
+ // ds->setForcedFixedWidth( dw, 400 );
+ // ds->setSeparatorPos(600, true);
+
+
+ d->config->setGroup("MainWindow");
+ ds->setSeparatorPosInPercent(d->config->readNumEntry("RightDockPosition", 80/* % */));
+// makeDockInvisible( manager()->findWidgetParentDock(d->propEditor) );
+
+ // ds->setForcedFixedWidth( dw, d->config->readNumEntry("RightDockPosition", 80) );
+ // ds->resize(400, ds->height());
+ // dw->resize(400, dw->height());
+ #endif
+
+ //1 dw->setMinimumWidth(200);
+
+ // ds->setSeparatorPos(d->propEditor->sizeHint().width(), true);
+
+ //heh, this is for IDEAl only, I suppose?
+ //js if (m_rightContainer) {
+ //js m_rightContainer->setForcedFixedWidth( 400 );
+ //js }
+ }
+
+ // int w = d->propEditor->width();
+ /* KMdiToolViewAccessor *tmp=createToolWindow();
+ tmp->setWidgetToWrap(d->propEditor);
+ d->propEditor->show(); // I'm not sure, if this is a bug in kdockwidget, which I would better fix there
+ tmp->show(KDockWidget::DockRight,getMainDockWidget(),20);
+ */
+ }
+// makeDockInvisible(manager()->findWidgetParentDock(d->propEditorTabWidget));
+}
+
+void KexiMainWindowImpl::slotPartLoaded(KexiPart::Part* p)
+{
+ if (!p)
+ return;
+ connect(p, SIGNAL(newObjectRequest(KexiPart::Info*)),
+ this, SLOT(newObject(KexiPart::Info*)));
+ p->createGUIClients(this);
+}
+
+//! internal
+void KexiMainWindowImpl::slotCaptionForCurrentMDIChild(bool childrenMaximized)
+{
+ //js todo: allow to set custom "static" app caption
+
+ KMdiChildView *view = 0L;
+ if (!d->curDialog)
+ view = 0;
+ else if (d->curDialog->isAttached()) {
+ view = d->curDialog;
+ } else {
+ //current dialog isn't attached! - find top level child
+ if (m_pMdi->topChild()) {
+ view = m_pMdi->topChild()->m_pClient;
+ childrenMaximized = view->mdiParent()->state()==KMdiChildFrm::Maximized;
+ }
+ else
+ view = 0;
+ }
+
+ if (childrenMaximized && view) {
+ setCaption( d->curDialog->caption()
+ + (d->appCaptionPrefix.isEmpty() ? QString::null : (QString::fromLatin1(" - ") + d->appCaptionPrefix)) );
+ }
+ else {
+ setCaption( (d->appCaptionPrefix.isEmpty() ? QString::null : (d->appCaptionPrefix + QString::fromLatin1(" - ")))
+ + d->origAppCaption );
+ }
+}
+
+void KexiMainWindowImpl::updateAppCaption()
+{
+ //js todo: allow to set custom "static" app caption
+
+ d->appCaptionPrefix = "";
+ if (d->prj && d->prj->data()) {//add project name
+ d->appCaptionPrefix = d->prj->data()->caption();
+ if (d->appCaptionPrefix.isEmpty())
+ d->appCaptionPrefix = d->prj->data()->databaseName();
+ }
+// if (!d->appCaptionPrefix.isEmpty())
+// d->appCaptionPrefix = d->appCaptionPrefix;
+
+ bool max = false;
+ if (d->curDialog && d->curDialog->mdiParent())
+ max = d->curDialog->mdiParent()->state()==KMdiChildFrm::Maximized;
+
+ slotCaptionForCurrentMDIChild(max);
+/*
+ KMdiChildView *view;
+ if (!d->curDialog)
+ view = 0;
+ else if (d->curDialog->isAttached()) {
+ view = d->curDialog;
+ } else {
+ //current dialog isn't attached! - find top level child
+ if (m_pMdi->topChild()) {
+ view = m_pMdi->topChild()->m_pClient;
+ }
+ else
+ view = 0;
+ }
+
+ kApp->setCaption( d->appCaption );
+ if (view && view->mdiParent()->state()==KMdiChildFrm::Maximized) {
+ setCaption( view->caption() );
+ }
+ else {
+ setCaption( d->appCaption );
+ }*/
+}
+
+void KexiMainWindowImpl::slotNoMaximizedChildFrmLeft(KMdiChildFrm*)
+{
+ slotCaptionForCurrentMDIChild(false);
+}
+
+void KexiMainWindowImpl::slotLastChildViewClosed() //slotLastChildFrmClosed()
+{
+ if (m_pDocumentViews->count()>0) //a fix for KMDI bug (will be fixed in KDE 3.4)
+ return;
+
+ slotCaptionForCurrentMDIChild(false);
+ activeWindowChanged(0);
+
+//js: too WEIRD if (d->propEditor)
+//js: too WEIRD makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
+// if (d->propEditorToolWindow)
+ // d->propEditorToolWindow->hide();
+}
+
+void KexiMainWindowImpl::slotChildViewIsDetachedNow(QWidget*)
+{
+ slotCaptionForCurrentMDIChild(false);
+}
+
+/*void
+KexiMainWindowImpl::closeEvent(QCloseEvent *ev)
+{
+ storeSettings();
+
+ bool cancelled = false;
+ if (!closeProject(cancelled)) {
+ //todo: error message
+ return;
+ }
+ if (cancelled) {
+ ev->ignore();
+ return;
+ }
+
+ ev->accept();
+}*/
+
+bool
+KexiMainWindowImpl::queryClose()
+{
+#ifndef KEXI_NO_PENDING_DIALOGS
+ if (d->pendingDialogsExist()) {
+ kdDebug() << "KexiMainWindowImpl::queryClose() pendingDialogsExist..." << endl;
+ d->actionToExecuteWhenPendingJobsAreFinished = Private::QuitAction;
+ return false;
+ }
+#endif
+// storeSettings();
+ const tristate res = closeProject();
+ if (~res)
+ return false;
+
+ if (res==true)
+ storeSettings();
+
+ return ! ~res;
+}
+
+bool
+KexiMainWindowImpl::queryExit()
+{
+// storeSettings();
+ return true;
+}
+
+void
+KexiMainWindowImpl::restoreSettings()
+{
+ d->config->setGroup("MainWindow");
+
+ // Saved settings
+ applyMainWindowSettings( d->config, "MainWindow" );
+
+ //small hack - set the default -- bottom
+// d->config->setGroup(QString(name()) + " KMdiTaskBar Toolbar style");
+ d->config->setGroup("MainWindow Toolbar KMdiTaskBar");
+ const bool tbe = d->config->readEntry("Position").isEmpty();
+ if (tbe || d->config->readEntry("Position")=="Bottom") {
+ if (tbe)
+ d->config->writeEntry("Position","Bottom");
+ moveDockWindow(m_pTaskBar, DockBottom);
+ }
+
+ d->config->setGroup("MainWindow");
+ int mdimode = d->config->readNumEntry("MDIMode", -1);//KMdi::TabPageMode);
+
+ const bool showProjectNavigator = d->config->readBoolEntry("ShowProjectNavigator", true);
+
+ switch(mdimode)
+ {
+/* case KMdi::ToplevelMode:
+ switchToToplevelMode();
+ m_pTaskBar->switchOn(true);
+ break;*/
+ case KMdi::ChildframeMode:
+ switchToChildframeMode(false);
+ m_pTaskBar->switchOn(true);
+
+ // restore a possible maximized Childframe mode,
+ // will be used in KexiMainWindowImpl::addWindow()
+ d->maximizeFirstOpenedChildFrm = d->config->readBoolEntry("maximized childframes", true);
+ setEnableMaximizedChildFrmMode(d->maximizeFirstOpenedChildFrm);
+
+ if (!showProjectNavigator) {
+ //it's visible by default but we want to hide it on navigator creation
+ d->forceHideProjectNavigatorOnCreation = true;
+ }
+
+ break;
+
+#define DEFAULT_MDI_MODE KMdi::IDEAlMode
+
+ case DEFAULT_MDI_MODE:
+ default:
+ switchToIDEAlMode(false);
+ if (showProjectNavigator) {
+ //it's invisible by default but we want to show it on navigator creation
+ d->forceShowProjectNavigatorOnCreation = true;
+ }
+ break;
+/* case KMdi::TabPageMode:
+ switchToTabPageMode();
+ break;
+*/
+ }
+
+#if 0
+ if ( !initialGeometrySet() ) {
+ // Default size
+// int restoredWidth, restoredHeight;
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+//#if KDE_IS_VERSION(3,1,90)
+// restoredWidth = KGlobalSettings::screenGeometry(scnum).width();
+ // restoredHeight = KGlobalSettings::screenGeometry(scnum).height();
+//#else
+// restoredWidth = QApplication::desktop()->width();
+// restoredHeight = QApplication::desktop()->height();
+//#endif
+/* if (restoredWidth > 1100) {// very big desktop ?
+ restoredWidth = 1000;
+ restoredHeight = 800;
+ }
+ if (restoredWidth > 850) {// big desktop ?
+ restoredWidth = 800;
+ restoredHeight = 600;
+ }
+ else {// small (800x600, 640x480) desktop
+ restoredWidth = QMIN( restoredWidth, 600 );
+ restoredHeight = QMIN( restoredHeight, 400 );
+ }*/
+
+ config->setGroup("MainWindow");
+ QSize s ( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 700 ),
+ config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 480 ) );
+ resize (kMin (s.width(), desk.width()), kMin(s.height(), desk.height()));
+ }
+#endif
+}
+
+void
+KexiMainWindowImpl::storeSettings()
+{
+ kdDebug() << "KexiMainWindowImpl::storeSettings()" << endl;
+
+// saveWindowSize( d->config ); //instance()->config() );
+ saveMainWindowSettings( d->config, "MainWindow" );
+ d->config->setGroup("MainWindow");
+ KMdi::MdiMode modeToSave = mdiMode();
+ if (d->mdiModeToSwitchAfterRestart!=(KMdi::MdiMode)0)
+ modeToSave = d->mdiModeToSwitchAfterRestart;
+ if (modeToSave == DEFAULT_MDI_MODE)
+ d->config->deleteEntry("MDIMode");
+ else
+ d->config->writeEntry("MDIMode", modeToSave);
+ d->config->writeEntry("maximized childframes", isInMaximizedChildFrmMode());
+
+// if (manager()->findWidgetParentDock(d->nav)->isVisible())
+ if (d->saveSettingsForShowProjectNavigator) {
+ if (d->navWasVisibleBeforeProjectClosing)
+ d->config->deleteEntry("ShowProjectNavigator");
+ else
+ d->config->writeEntry("ShowProjectNavigator", false);
+ }
+
+ if (modeToSave==KMdi::ChildframeMode || modeToSave==KMdi::TabPageMode) {
+ if (d->propEditor && d->propEditorDockSeparatorPos >= 0 && d->propEditorDockSeparatorPos <= 100) {
+ d->config->setGroup("MainWindow");
+ d->config->writeEntry("RightDockPosition", d->propEditorDockSeparatorPos);
+ }
+ else
+ d->propEditorDockSeparatorPos = 80;
+ if (d->nav && d->navDockSeparatorPos >= 0 && d->navDockSeparatorPos <= 100) {
+ d->config->setGroup("MainWindow");
+ //KDockWidget *dw = (KDockWidget *)d->nav->parentWidget();
+ //int w = dw->width();
+ //int ww = width();
+ //int d1 = (100 * dw->width()) / width() + 1;
+ //KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ //int d2 = ds->separatorPosInPercent();
+ if (d->wasAutoOpen && d->dialogExistedBeforeCloseProject) {
+#ifdef Q_WS_WIN
+ d->config->writeEntry("LeftDockPositionWithAutoOpen",
+ d->navDockSeparatorPos);
+#endif
+// d->config->writeEntry("LeftDockPosition", dw->width());
+// d->config->writeEntry("LeftDockPosition", d->nav->width());
+ } else {
+#ifdef Q_WS_WIN
+ if (d->dialogExistedBeforeCloseProject)
+ d->config->writeEntry("LeftDockPosition", d->navDockSeparatorPos);
+ else
+ d->config->writeEntry("LeftDockPosition", qRound(double(d->navDockSeparatorPos) / 0.77
+ / (double(d->propEditorDockSeparatorPos) / 80) ));
+#endif
+ }
+ }
+ }
+
+ if (d->propEditor) {
+ d->config->setGroup("PropertyEditor");
+ d->config->writeEntry("FontSize", d->propEditorTabWidget->font().pixelSize());
+ }
+}
+
+void
+KexiMainWindowImpl::restoreWindowConfiguration(KConfig *config)
+{
+ kdDebug()<<"preparing session restoring"<<endl;
+
+ config->setGroup("MainWindow");
+
+ QString dockGrp;
+
+ if (kapp->isRestored())
+ dockGrp=config->group()+"-Docking";
+ else
+ dockGrp="MainWindow0-Docking";
+
+ if (config->hasGroup(dockGrp))
+ readDockConfig(config,dockGrp);
+}
+
+void
+KexiMainWindowImpl::storeWindowConfiguration(KConfig *config)
+{
+ kdDebug()<<"preparing session saving"<<endl;
+ config->setGroup("MainWindow");
+ QString dockGrp;
+
+#if KDE_IS_VERSION(3,1,9) && !defined(Q_WS_WIN)
+ if (kapp->sessionSaving())
+ dockGrp=config->group()+"-Docking";
+ else
+#endif
+ dockGrp="MainWindow0-Docking";
+
+ kdDebug()<<"Before write dock config"<<endl;
+ writeDockConfig(config,dockGrp);
+ kdDebug()<<"After write dock config"<<endl;
+}
+
+void
+KexiMainWindowImpl::readProperties(KConfig *config) {
+ restoreWindowConfiguration(config);
+}
+
+void
+KexiMainWindowImpl::saveProperties(KConfig *config)
+{
+ storeWindowConfiguration(config);
+// m_docManager->saveDocumentList (config);
+ // m_projectManager->saveProjectList (config);
+}
+
+void
+KexiMainWindowImpl::saveGlobalProperties( KConfig* sessionConfig ) {
+ storeWindowConfiguration(sessionConfig);
+}
+
+void
+KexiMainWindowImpl::registerChild(KexiDialogBase *dlg)
+{
+ kdDebug() << "KexiMainWindowImpl::registerChild()" << endl;
+ connect(dlg, SIGNAL(activated(KMdiChildView *)),
+ this, SLOT(activeWindowChanged(KMdiChildView *)));
+ connect(dlg, SIGNAL(dirtyChanged(KexiDialogBase*)),
+ this, SLOT(slotDirtyFlagChanged(KexiDialogBase*)));
+
+// connect(dlg, SIGNAL(childWindowCloseRequest(KMdiChildView *)), this, SLOT(childClosed(KMdiChildView *)));
+ if(dlg->id() != -1) {
+ d->insertDialog(dlg);
+ }
+ kdDebug() << "KexiMainWindowImpl::registerChild() ID = " << dlg->id() << endl;
+
+ if (m_mdiMode==KMdi::ToplevelMode || m_mdiMode==KMdi::ChildframeMode) {//kmdi fix
+ //js TODO: check if taskbar is switched in menu
+ if (m_pTaskBar && !m_pTaskBar->isSwitchedOn())
+ m_pTaskBar->switchOn(true);
+ }
+ //KMdiChildFrm *frm = dlg->mdiParent();
+ //if (frm) {
+// dlg->setMargin(20);
+ //dlg->setLineWidth(20);
+ //}
+}
+
+void
+KexiMainWindowImpl::updateDialogViewGUIClient(KXMLGUIClient *viewClient)
+{
+ if (viewClient!=d->curDialogViewGUIClient) {
+ //view clients differ
+ kdDebug()<<"KexiMainWindowImpl::activeWindowChanged(): old view gui client:"
+ <<(d->curDialogViewGUIClient ? d->curDialogViewGUIClient->xmlFile() : "")
+ <<" new view gui client: "<<( viewClient ? viewClient->xmlFile() : "") <<endl;
+ if (d->curDialogViewGUIClient) {
+ guiFactory()->removeClient(d->curDialogViewGUIClient);
+ }
+ if (viewClient) {
+ if (d->closedDialogViewGUIClient) {
+ //ooh, there is a client which dialog is already closed -- BUT it is the same client as our
+ //so: give up
+ }
+ else {
+ guiFactory()->addClient(viewClient);
+ }
+ }
+ }
+}
+
+void KexiMainWindowImpl::updateCustomPropertyPanelTabs(KexiDialogBase *prevDialog, int prevViewMode)
+{
+ updateCustomPropertyPanelTabs(
+ prevDialog ? prevDialog->part() : 0,
+ prevDialog ? prevDialog->currentViewMode() : prevViewMode,
+ d->curDialog ? d->curDialog->part() : 0,
+ d->curDialog ? d->curDialog->currentViewMode() : Kexi::NoViewMode
+ );
+}
+
+void KexiMainWindowImpl::updateCustomPropertyPanelTabs(
+ KexiPart::Part *prevDialogPart, int prevViewMode, KexiPart::Part *curDialogPart, int curViewMode )
+{
+ if (!d->propEditorTabWidget)
+ return;
+
+ if (!curDialogPart
+ || (/*prevDialogPart &&*/ curDialogPart
+ && (prevDialogPart!=curDialogPart || prevViewMode!=curViewMode)
+ ))
+ {
+ if (d->partForPreviouslySetupPropertyPanelTabs) {
+ //remember current page number for this part
+ if (prevViewMode==Kexi::DesignViewMode &&
+ ((KexiPart::Part*)d->partForPreviouslySetupPropertyPanelTabs != curDialogPart) //part changed
+ || curViewMode!=Kexi::DesignViewMode) //..or switching to other view mode
+ {
+ d->recentlySelectedPropertyPanelPages.insert( d->partForPreviouslySetupPropertyPanelTabs,
+ d->propEditorTabWidget->currentPageIndex() );
+ }
+ }
+
+ //delete old custom tabs (other than 'property' tab)
+ const uint count = d->propEditorTabWidget->count();
+ for (uint i=1; i < count; i++)
+ d->propEditorTabWidget->removePage( d->propEditorTabWidget->page(1) );
+ }
+
+ //don't change anything if part is not switched nor view mode changed
+ if ((!prevDialogPart && !curDialogPart)
+ || (prevDialogPart == curDialogPart && prevViewMode==curViewMode)
+ || (curDialogPart && curViewMode!=Kexi::DesignViewMode))
+ {
+ //new part for 'previously setup tabs'
+ d->partForPreviouslySetupPropertyPanelTabs = curDialogPart;
+ return;
+ }
+
+ if (curDialogPart) {
+ //recreate custom tabs
+ curDialogPart->setupCustomPropertyPanelTabs(d->propEditorTabWidget, this);
+
+ //restore current page number for this part
+ if (d->recentlySelectedPropertyPanelPages.contains( curDialogPart )) {
+ d->propEditorTabWidget->setCurrentPage(
+ d->recentlySelectedPropertyPanelPages[ curDialogPart ]
+ );
+ }
+ }
+
+ //new part for 'previously setup tabs'
+ d->partForPreviouslySetupPropertyPanelTabs = curDialogPart;
+}
+
+void KexiMainWindowImpl::activeWindowChanged(KMdiChildView *v)
+{
+ KexiDialogBase *dlg = static_cast<KexiDialogBase *>(v);
+ kdDebug() << "KexiMainWindowImpl::activeWindowChanged() to = " << (dlg ? dlg->caption() : "<none>") << endl;
+
+ KXMLGUIClient *client=0; //common for all views
+ KXMLGUIClient *viewClient=0; //specific for current dialog's view
+ KexiDialogBase* prevDialog = d->curDialog;
+
+ if (!dlg)
+ client=0;
+ else if ( dlg->isRegistered()) {
+// client=dlg->guiClient();
+ client=dlg->commonGUIClient();
+ viewClient=dlg->guiClient();
+ if (d->closedDialogGUIClient) {
+ if (client!=d->closedDialogGUIClient) {
+ //ooh, there is a client which dialog is already closed -- and we don't want it
+ guiFactory()->removeClient(d->closedDialogGUIClient);
+ d->closedDialogGUIClient=0;
+ }
+ }
+ if (d->closedDialogViewGUIClient) {
+ if (viewClient!=d->closedDialogViewGUIClient) {
+ //ooh, there is a client which dialog is already closed -- and we don't want it
+ guiFactory()->removeClient(d->closedDialogViewGUIClient);
+ d->closedDialogViewGUIClient=0;
+ }
+ }
+ if (client!=d->curDialogGUIClient) {
+ //clients differ
+ kdDebug()<<"KexiMainWindowImpl::activeWindowChanged(): old gui client:"
+ <<(d->curDialogGUIClient ? d->curDialogGUIClient->xmlFile() : "")
+ <<" new gui client: "<<( client ? client->xmlFile() : "") <<endl;
+ if (d->curDialogGUIClient) {
+ guiFactory()->removeClient(d->curDialogGUIClient);
+ d->curDialog->detachFromGUIClient();
+ }
+ if (client) {
+ if (d->closedDialogGUIClient) {
+ //ooh, there is a client which dialog is already closed -- BUT it is the same client as our
+ //so: give up
+ }
+ else {
+ guiFactory()->addClient(client);
+ }
+ dlg->attachToGUIClient();
+ }
+ } else {
+ //clients are the same
+ if ((KexiDialogBase*)d->curDialog!=dlg) {
+ if (d->curDialog)
+ d->curDialog->detachFromGUIClient();
+ if (dlg)
+ dlg->attachToGUIClient();
+ }
+ }
+ updateDialogViewGUIClient(viewClient);
+/* if (viewClient!=d->curDialogViewGUIClient) {
+ //view clients differ
+ kdDebug()<<"KexiMainWindowImpl::activeWindowChanged(): old view gui client:"
+ <<d->curDialogViewGUIClient<<" new view gui client: "<<viewClient<<endl;
+ if (d->curDialogViewGUIClient) {
+ guiFactory()->removeClient(d->curDialogViewGUIClient);
+ }
+ if (viewClient) {
+ if (d->closedDialogViewGUIClient) {
+ //ooh, there is a client which dialog is already closed -- BUT it is the same client as our
+ //so: give up
+ }
+ else {
+ guiFactory()->addClient(viewClient);
+ }
+ }
+ }*/
+ }
+ bool update_dlg_caption = dlg && dlg!=(KexiDialogBase*)d->curDialog && dlg->mdiParent();
+
+ if (d->curDialogGUIClient && !client)
+ guiFactory()->removeClient(d->curDialogGUIClient);
+ d->curDialogGUIClient=client;
+
+ if (d->curDialogViewGUIClient && !viewClient)
+ guiFactory()->removeClient(d->curDialogViewGUIClient);
+ d->curDialogViewGUIClient=viewClient;
+
+ bool dialogChanged = ((KexiDialogBase*)d->curDialog)!=dlg;
+
+ if (dialogChanged) {
+ if (d->curDialog) {
+ //inform previously activated dialog about deactivation
+ d->curDialog->deactivate();
+ }
+ }
+ d->curDialog=dlg;
+
+//moved below: propertySetSwitched(d->curDialog);
+
+ updateCustomPropertyPanelTabs(prevDialog, prevDialog ? prevDialog->currentViewMode() : Kexi::NoViewMode);
+
+ // inform the current view of the new dialog about property switching
+ // (this will also call KexiMainWindowImpl::propertySetSwitched() to update the current property editor's set
+ if (dialogChanged && d->curDialog)
+ d->curDialog->selectedView()->propertySetSwitched();
+
+ if (dialogChanged) {
+// invalidateSharedActions();
+ //update property editor's contents...
+// if ((KexiPropertyBuffer*)d->propBuffer!=d->curDialog->propertyBuffer()) {
+// propertyBufferSwitched();//d->curDialog);
+// d->propBuffer = d->curDialog->propertyBuffer();
+// d->propEditor->editor()->setBuffer( d->propBuffer );
+// }
+ if (d->curDialog && d->curDialog->currentViewMode()!=0) //on opening new dialog it can be 0; we don't want this
+ d->updatePropEditorVisibility(d->curDialog->currentViewMode());
+ }
+
+ //update caption...
+ if (update_dlg_caption) {//d->curDialog is != null for sure
+ slotCaptionForCurrentMDIChild(d->curDialog->mdiParent()->state()==KMdiChildFrm::Maximized);
+ }
+// if (!d->curDialog.isNull())
+// d->last_checked_mode = d->actions_for_view_modes[ d->curDialog->currentViewMode() ];
+ invalidateViewModeActions();
+ invalidateActions();
+ d->updateFindDialogContents();
+ if (dlg)
+ dlg->setFocus();
+}
+
+bool
+KexiMainWindowImpl::activateWindow(int id)
+{
+ kdDebug() << "KexiMainWindowImpl::activateWindow()" << endl;
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ return activateWindow( d->openedDialogFor( id, pendingType ) );
+#else
+ return activateWindow( d->openedDialogFor( id ) );
+#endif
+}
+
+bool
+KexiMainWindowImpl::activateWindow(KexiDialogBase *dlg)
+{
+ kdDebug() << "KexiMainWindowImpl::activateWindow(KexiDialogBase *)" << endl;
+ if(!dlg)
+ return false;
+
+ d->focus_before_popup = dlg;
+ dlg->activate();
+ return true;
+}
+
+void
+KexiMainWindowImpl::childClosed(KMdiChildView *v)
+{
+ KexiDialogBase *dlg = static_cast<KexiDialogBase *>(v);
+ d->removeDialog(dlg->id());
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog(dlg->id());
+#endif
+
+ //focus navigator if nothing else available
+ if (d->openedDialogsCount() == 0)
+ d->nav->setFocus();
+}
+
+void
+KexiMainWindowImpl::slotShowSettings()
+{
+ KEXI_UNFINISHED(d->action_configure->text());
+//TODO KexiSettings s(this);
+// s.exec();
+}
+
+void
+KexiMainWindowImpl::slotConfigureKeys()
+{
+/* KKeyDialog dlg;
+ dlg.insert( actionCollection() );
+ dlg.configure();*/
+ KKeyDialog::configure( actionCollection(), false/*bAllowLetterShortcuts*/, this );
+}
+
+void
+KexiMainWindowImpl::slotConfigureToolbars()
+{
+ KEditToolbar edit(factory());
+// connect(&edit,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
+ (void) edit.exec();
+}
+
+void
+KexiMainWindowImpl::slotProjectNew()
+{
+ if (!d->prj) {
+ //create within this instance
+ createBlankProject();
+ return;
+ }
+//TODO use KexiStartupDialog(KexiStartupDialog::Templates...)
+
+ bool cancel;
+ QString fileName;
+ KexiProjectData *new_data = createBlankProjectData(
+ cancel,
+ false, /* do not confirm prj overwrites: user will be asked on process startup */
+ &fileName //shortcut fname
+ );
+ if (!new_data)
+ return;
+
+ QStringList args;
+ args << qApp->applicationFilePath() << "-create-opendb";
+ if (new_data->connectionData()->fileName().isEmpty()) {
+ //server based - pass .kexic file
+ if (fileName.isEmpty())
+ return;
+ args << new_data->databaseName() << fileName;
+ //args << "--skip-conn-dialog"; //user does not expect conn. dialog to be shown here
+ }
+ else {
+ //file based
+ fileName = new_data->connectionData()->fileName();
+ args << fileName;
+ }
+//todo: pass new_data->caption()
+ //start new instance
+//! @todo use KProcess?
+ QProcess proc(args, this, "process");
+ proc.setCommunication((QProcess::Communication)0);
+// proc.setWorkingDirectory( QFileInfo(new_data->connectionData()->fileName()).dir(true) );
+ proc.setWorkingDirectory( QFileInfo(fileName).dir(true) );
+ if (!proc.start()) {
+ d->showStartProcessMsg(args);
+ }
+ delete new_data;
+}
+
+void
+KexiMainWindowImpl::createKexiProject(KexiProjectData* new_data)
+{
+ d->prj = new KexiProject( new_data, this );
+// d->prj = ::createKexiProject(new_data);
+//provided by KexiMessageHandler connect(d->prj, SIGNAL(error(const QString&,KexiDB::Object*)), this, SLOT(showErrorMessage(const QString&,KexiDB::Object*)));
+//provided by KexiMessageHandler connect(d->prj, SIGNAL(error(const QString&,const QString&)), this, SLOT(showErrorMessage(const QString&,const QString&)));
+ connect(d->prj, SIGNAL(itemRenamed(const KexiPart::Item&, const QCString&)), this, SLOT(slotObjectRenamed(const KexiPart::Item&, const QCString&)));
+
+ if (d->nav)
+ connect(d->prj, SIGNAL(itemRemoved(const KexiPart::Item&)), d->nav, SLOT(slotRemoveItem(const KexiPart::Item&)));
+}
+
+KexiProjectData*
+KexiMainWindowImpl::createBlankProjectData(bool &cancelled, bool confirmOverwrites,
+ QString* shortcutFileName)
+{
+ cancelled = false;
+ KexiNewProjectWizard wiz(Kexi::connset(), 0, "KexiNewProjectWizard", true);
+ wiz.setConfirmOverwrites(confirmOverwrites);
+ if (wiz.exec() != QDialog::Accepted) {
+ cancelled=true;
+ return 0;
+ }
+
+ KexiProjectData *new_data;
+
+ if (shortcutFileName)
+ *shortcutFileName = QString::null;
+ if (wiz.projectConnectionData()) {
+ //server-based project
+ KexiDB::ConnectionData *cdata = wiz.projectConnectionData();
+ kdDebug() << "DBNAME: " << wiz.projectDBName() << " SERVER: " << cdata->serverInfoString() << endl;
+ new_data = new KexiProjectData( *cdata, wiz.projectDBName(), wiz.projectCaption() );
+ if (shortcutFileName)
+ *shortcutFileName = Kexi::connset().fileNameForConnectionData(cdata);
+ }
+ else if (!wiz.projectDBName().isEmpty()) {
+ //file-based project
+ KexiDB::ConnectionData cdata;
+ cdata.caption = wiz.projectCaption();
+ cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
+ cdata.setFileName( wiz.projectDBName() );
+ new_data = new KexiProjectData( cdata, wiz.projectDBName(), wiz.projectCaption() );
+ }
+ else {
+ cancelled = true;
+ return 0;
+ }
+ return new_data;
+}
+
+tristate
+KexiMainWindowImpl::createBlankProject()
+{
+ bool cancel;
+ KexiProjectData *new_data = createBlankProjectData(cancel);
+ if (cancel)
+ return cancelled;
+ if (!new_data)
+ return false;
+
+ createKexiProject( new_data );
+
+ tristate res = d->prj->create(true /*overwrite*/ );
+ if (res != true) {
+ delete d->prj;
+ d->prj = 0;
+ return res;
+ }
+ kdDebug() << "KexiMainWindowImpl::slotProjectNew(): new project created --- " << endl;
+ initNavigator();
+ Kexi::recentProjects().addProjectData( new_data );
+
+ invalidateActions();
+ updateAppCaption();
+ return true;
+}
+
+void
+KexiMainWindowImpl::slotProjectOpen()
+{
+ KexiStartupDialog dlg(
+ KexiStartupDialog::OpenExisting, 0, Kexi::connset(), Kexi::recentProjects(),
+ this, "KexiOpenDialog");
+
+ if (dlg.exec()!=QDialog::Accepted)
+ return;
+
+ openProject(dlg.selectedFileName(), dlg.selectedExistingConnection());
+}
+
+tristate KexiMainWindowImpl::openProject(const QString& aFileName,
+ const QString& fileNameForConnectionData, const QString& dbName)
+{
+ if (d->prj)
+ return openProjectInExternalKexiInstance(aFileName, fileNameForConnectionData, dbName);
+
+ KexiDB::ConnectionData *cdata = 0;
+ if (!fileNameForConnectionData.isEmpty()) {
+ cdata = Kexi::connset().connectionDataForFileName( fileNameForConnectionData );
+ if (!cdata) {
+ kdWarning() << "KexiMainWindowImpl::openProject() cdata?" << endl;
+ return false;
+ }
+ }
+ return openProject(aFileName, cdata, dbName);
+}
+
+tristate KexiMainWindowImpl::openProject(const QString& aFileName,
+ KexiDB::ConnectionData *cdata, const QString& dbName,
+ const QValueList<KexiProjectData::ObjectInfo>& autoopenObjects)
+{
+ if (d->prj) {
+ return openProjectInExternalKexiInstance(aFileName, cdata, dbName);
+ }
+
+ KexiProjectData* projectData = 0;
+ bool deleteAfterOpen = false;
+ if (cdata) {
+ //server-based project
+ if (dbName.isEmpty()) {//no database name given, ask user
+ bool cancel;
+ projectData = Kexi::startupHandler().selectProject( cdata, cancel, this );
+ if (cancel)
+ return cancelled;
+ }
+ else {
+//! @todo caption arg?
+ projectData = new KexiProjectData( *cdata, dbName );
+ deleteAfterOpen = true;
+ }
+ }
+ else {
+// QString selFile = dlg.selectedExistingFile();
+ if (aFileName.isEmpty()) {
+ kdWarning() << "KexiMainWindowImpl::openProject(): aFileName.isEmpty()" << endl;
+ return false;
+ }
+ //file-based project
+ kdDebug() << "Project File: " << aFileName << endl;
+ KexiDB::ConnectionData cdata;
+ cdata.setFileName( aFileName );
+// cdata.driverName = KexiStartupHandler::detectDriverForFile( cdata.driverName, fileName, this );
+ QString detectedDriverName;
+ KexiStartupData::Import importActionData;
+ const tristate res = KexiStartupHandler::detectActionForFile(
+ importActionData, detectedDriverName, cdata.driverName, aFileName, this );
+ if (true != res)
+ return res;
+
+ if (importActionData) { //importing requested
+ return showProjectMigrationWizard( importActionData.mimeType, importActionData.fileName );
+ }
+ cdata.driverName = detectedDriverName;
+
+ if (cdata.driverName.isEmpty())
+ return false;
+
+ //opening requested
+ projectData = new KexiProjectData(cdata, aFileName);
+ deleteAfterOpen = true;
+ }
+ if (!projectData)
+ return false;
+ projectData->autoopenObjects = autoopenObjects;
+ const tristate res = openProject(*projectData);
+ if (deleteAfterOpen) //projectData object has been copied
+ delete projectData;
+ return res;
+}
+
+tristate KexiMainWindowImpl::openProjectInExternalKexiInstance(const QString& aFileName,
+ KexiDB::ConnectionData *cdata, const QString& dbName)
+{
+ QString fileNameForConnectionData;
+ if (aFileName.isEmpty()) { //try .kexic file
+ if (cdata)
+ fileNameForConnectionData = Kexi::connset().fileNameForConnectionData(cdata);
+ }
+ return openProjectInExternalKexiInstance(aFileName, fileNameForConnectionData, dbName);
+}
+
+tristate KexiMainWindowImpl::openProjectInExternalKexiInstance(const QString& aFileName,
+ const QString& fileNameForConnectionData, const QString& dbName)
+{
+ QString fileName(aFileName);
+ QStringList args;
+ args << qApp->applicationFilePath();
+ // open a file-based project or a server connection provided as a .kexic file
+ // (we have no other simple way to provide the startup data to a new process)
+ if (fileName.isEmpty()) { //try .kexic file
+ if (!fileNameForConnectionData.isEmpty())
+ args << "--skip-conn-dialog"; //user does not expect conn. dialog to be shown here
+
+ if (dbName.isEmpty()) { //use 'kexi --skip-conn-dialog file.kexic'
+ fileName = fileNameForConnectionData;
+ }
+ else { //use 'kexi --skip-conn-dialog --connection file.kexic dbName'
+ args << "--connection" << fileNameForConnectionData;
+ fileName = dbName;
+ }
+ }
+ if (fileName.isEmpty()) {
+ kdWarning() << "KexiMainWindowImpl::openProjectInExternalKexiInstance() fileName?" << endl;
+ return false;
+ }
+//! @todo use KRun
+ args << fileName;
+ QProcess proc(args, this, "process");
+ proc.setWorkingDirectory( QFileInfo(fileName).dir(true) );
+ const bool ok = proc.start();
+ if (!ok) {
+ d->showStartProcessMsg(args);
+ }
+ return ok;
+}
+
+void
+KexiMainWindowImpl::slotProjectOpenRecentAboutToShow()
+{
+ /*
+ //setup
+ KPopupMenu *popup = d->action_open_recent->popupMenu();
+ const int cnt = popup->count();
+ //remove older
+ for (int i = 0; i<cnt; i++) {
+ int id = popup->idAt(0);
+ if (id==d->action_open_recent_more_id)
+ break;
+ if (id>=0) {
+ popup->removeItem(id);
+ }
+ }
+ //insert current items
+ int cur_id = 0, cur_idx = 0;
+ //TODO:
+ cur_id = popup->insertItem("My example project 1", ++cur_id, cur_idx++);
+ cur_id = popup->insertItem("My example project 2", ++cur_id, cur_idx++);
+ cur_id = popup->insertItem("My example project 3", ++cur_id, cur_idx++);
+ */
+
+ //show recent databases
+ KPopupMenu *popup = d->action_open_recent->popupMenu();
+ popup->clear();
+#if 0
+ d->action_open_recent_projects_title_id = popup->insertTitle(i18n("Recently Opened Databases"));
+#endif
+// int action_open_recent_projects_title_index = popup->indexOf(d->action_open_recent_projects_title_id);
+// int count = popup->count();
+// int action_open_recent_connections_title_index = popup->indexOf(d->action_open_recent_connections_title_id);
+// for (int i=action_open_recent_projects_title_index+1;
+// i<action_open_recent_connections_title_index; i++)
+// {
+// popup->removeItemAt(action_open_recent_projects_title_index+1);
+// }
+
+// int cur_idx = action_open_recent_projects_title_index+1;
+ popup->insertItem(SmallIconSet("kexiproject_sqlite"), "My project 1");
+ popup->insertItem(SmallIconSet("kexiproject_sqlite"), "My project 2");
+ popup->insertItem(SmallIconSet("kexiproject_sqlite"), "My project 3");
+
+#if 0
+ //show recent connections
+ d->action_open_recent_connections_title_id =
+ d->action_open_recent->popupMenu()->insertTitle(i18n("Recently Connected Database Servers"));
+
+// cur_idx = popup->indexOf(d->action_open_recent_connections_title_id) + 1;
+// for (int i=cur_idx; i<count; i++) {
+// popup->removeItemAt(cur_idx);
+// }
+ popup->insertItem(SmallIconSet("socket"), "My connection 1");
+ popup->insertItem(SmallIconSet("socket"), "My connection 2");
+ popup->insertItem(SmallIconSet("socket"), "My connection 3");
+ popup->insertItem(SmallIconSet("socket"), "My connection 4");
+#endif
+}
+
+void
+KexiMainWindowImpl::slotProjectOpenRecent(int id)
+{
+ if (id<0) // || id==d->action_open_recent_more_id)
+ return;
+ kdDebug() << "KexiMainWindowImpl::slotProjectOpenRecent("<<id<<")"<<endl;
+}
+
+void
+KexiMainWindowImpl::slotProjectOpenRecentMore()
+{
+ KEXI_UNFINISHED(i18n("Open Recent"));
+}
+
+void
+KexiMainWindowImpl::slotProjectSave()
+{
+ if (!d->curDialog)
+ return;
+ saveObject( d->curDialog );
+ updateAppCaption();
+ invalidateActions();
+}
+
+void
+KexiMainWindowImpl::slotProjectSaveAs()
+{
+ KEXI_UNFINISHED(i18n("Save object as"));
+}
+
+void
+KexiMainWindowImpl::slotProjectPrint()
+{
+ if (d->curDialog && d->curDialog->partItem())
+ printItem(d->curDialog->partItem());
+}
+
+void
+KexiMainWindowImpl::slotProjectPrintPreview()
+{
+ if (d->curDialog && d->curDialog->partItem())
+ printPreviewForItem(d->curDialog->partItem());
+}
+
+void
+KexiMainWindowImpl::slotProjectPageSetup()
+{
+ if (d->curDialog && d->curDialog->partItem())
+ showPageSetupForItem(d->curDialog->partItem());
+}
+
+void KexiMainWindowImpl::slotProjectExportDataTable()
+{
+ if (d->curDialog && d->curDialog->partItem())
+ exportItemAsDataTable(d->curDialog->partItem());
+}
+
+void
+KexiMainWindowImpl::slotProjectProperties()
+{
+ //TODO: load the implementation not the ui :)
+// ProjectSettingsUI u(this);
+// u.exec();
+}
+
+void
+KexiMainWindowImpl::slotProjectClose()
+{
+ closeProject();
+}
+
+void KexiMainWindowImpl::slotProjectRelations()
+{
+ if (!d->prj)
+ return;
+ KexiDialogBase *d = KexiInternalPart::createKexiDialogInstance("relation", this, this);
+ activateWindow(d);
+}
+
+void KexiMainWindowImpl::slotImportFile()
+{
+ KEXI_UNFINISHED("Import: " + i18n("From File..."));
+}
+
+void KexiMainWindowImpl::slotImportServer()
+{
+ KEXI_UNFINISHED("Import: " + i18n("From Server..."));
+}
+
+void
+KexiMainWindowImpl::slotProjectQuit()
+{
+ if (~ closeProject())
+ return;
+ close();
+}
+
+void KexiMainWindowImpl::slotViewNavigator()
+{
+ if (!d->nav || !d->navToolWindow)
+ return;
+ if (!d->nav->isVisible())
+ makeWidgetDockVisible(d->nav);
+// makeDockVisible(dynamic_cast<KDockWidget*>(d->navToolWindow->wrapperWidget()));
+// d->navToolWindow->wrapperWidget()->show();
+// d->navToolWindow->show(KDockWidget::DockLeft, getMainDockWidget());
+
+ d->navToolWindow->wrapperWidget()->raise();
+//
+ d->block_KMdiMainFrm_eventFilter=true;
+ d->nav->setFocus();
+ d->block_KMdiMainFrm_eventFilter=false;
+}
+
+void KexiMainWindowImpl::slotViewMainArea()
+{
+ if (d->curDialog)
+ d->curDialog->setFocus();
+}
+
+void KexiMainWindowImpl::slotViewPropertyEditor()
+{
+ if (!d->propEditor || !d->propEditorToolWindow)
+ return;
+
+//js d->config->setGroup("MainWindow");
+//js ds->setSeparatorPos(d->config->readNumEntry("RightDockPosition", 80/* % */), true);
+
+ if (!d->propEditorTabWidget->isVisible())
+ makeWidgetDockVisible(d->propEditorTabWidget);
+
+
+ d->propEditorToolWindow->wrapperWidget()->raise();
+
+ d->block_KMdiMainFrm_eventFilter=true;
+ if (d->propEditorTabWidget->currentPage())
+ d->propEditorTabWidget->currentPage()->setFocus();
+ d->block_KMdiMainFrm_eventFilter=false;
+
+/*#if defined(KDOCKWIDGET_P)
+ KDockWidget *dw = (KDockWidget *)d->propEditor->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ ds->setSeparatorPos(80,true);//d->config->readNumEntry("RightDockPosition", 80), true);
+#endif*/
+}
+
+bool KexiMainWindowImpl::switchToViewMode(int viewMode)
+{
+ if (!d->curDialog) {
+ d->toggleLastCheckedMode();
+ return false;
+ }
+ if (!d->curDialog->supportsViewMode( viewMode )) {
+ showErrorMessage(i18n("Selected view is not supported for \"%1\" object.")
+ .arg(d->curDialog->partItem()->name()),
+ i18n("Selected view (%1) is not supported by this object type (%2).")
+ .arg(Kexi::nameForViewMode(viewMode))
+ .arg(d->curDialog->part()->instanceCaption()) );
+ d->toggleLastCheckedMode();
+ return false;
+ }
+ int prevViewMode = d->curDialog->currentViewMode();
+ updateCustomPropertyPanelTabs(d->curDialog->part(), prevViewMode,
+ d->curDialog->part(), viewMode );
+ tristate res = d->curDialog->switchToViewMode( viewMode );
+ if (!res) {
+ updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert
+ showErrorMessage(i18n("Switching to other view failed (%1).").arg(Kexi::nameForViewMode(viewMode)),
+ d->curDialog);
+ d->toggleLastCheckedMode();
+ return false;
+ }
+ if (~res) {
+ updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert
+ d->toggleLastCheckedMode();
+ return false;
+ }
+
+ //view changed: switch to this view's gui client
+ KXMLGUIClient *viewClient=d->curDialog->guiClient();
+ updateDialogViewGUIClient(viewClient);
+ if (d->curDialogViewGUIClient && !viewClient)
+ guiFactory()->removeClient(d->curDialogViewGUIClient);
+ d->curDialogViewGUIClient=viewClient; //remember
+
+ d->updatePropEditorVisibility(viewMode);
+ invalidateProjectWideActions();
+ invalidateSharedActions();
+ d->updateFindDialogContents();
+ return true;
+}
+
+
+void KexiMainWindowImpl::slotViewDataMode()
+{
+ switchToViewMode(Kexi::DataViewMode);
+}
+
+void KexiMainWindowImpl::slotViewDesignMode()
+{
+ switchToViewMode(Kexi::DesignViewMode);
+}
+
+void KexiMainWindowImpl::slotViewTextMode()
+{
+ switchToViewMode(Kexi::TextViewMode);
+}
+
+void KexiMainWindowImpl::closeWindow(KMdiChildView *pWnd, bool layoutTaskBar)
+{
+ if (d->insideCloseDialog && dynamic_cast<KexiDialogBase *>(pWnd)) {
+ d->windowsToClose.append(dynamic_cast<KexiDialogBase *>(pWnd));
+ return;
+ }
+ /*moved to closeDialog()
+ if (pWnd == d->curDialog && !pWnd->isAttached()) {
+ if (d->propEditor) {
+ // ah, closing detached window - better switch off property buffer right now...
+ d->propBuffer = 0;
+ d->propEditor->editor()->setBuffer( 0, false );
+ }
+ }
+ */
+ closeDialog(dynamic_cast<KexiDialogBase *>(pWnd), layoutTaskBar);
+}
+
+tristate KexiMainWindowImpl::getNewObjectInfo(
+ KexiPart::Item *partItem, KexiPart::Part *part,
+ bool& allowOverwriting, const QString& messageWhenAskingForName )
+{
+ //data was never saved in the past -we need to create a new object at the backend
+ KexiPart::Info *info = part->info();
+#ifdef KEXI_ADD_CUSTOM_OBJECT_CREATION
+# include "keximainwindowimpl_customobjcreation.h"
+#endif
+ if (!d->nameDialog) {
+ d->nameDialog = new KexiNameDialog(
+ messageWhenAskingForName, this, "nameDialog");
+ //check if that name is allowed
+ d->nameDialog->widget()->addNameSubvalidator(
+ new KexiDB::ObjectNameValidator(project()->dbConnection()->driver(), 0, "sub"));
+ }
+ else {
+ d->nameDialog->widget()->setMessageText( messageWhenAskingForName );
+ }
+ d->nameDialog->widget()->setCaptionText(partItem->caption());
+ d->nameDialog->widget()->setNameText(partItem->name());
+ d->nameDialog->setCaption(i18n("Save Object As"));
+ d->nameDialog->setDialogIcon( DesktopIcon( info->itemIcon(), KIcon::SizeMedium ) );
+ allowOverwriting = false;
+ bool found;
+ do {
+ if (d->nameDialog->exec()!=QDialog::Accepted)
+ return cancelled;
+ //check if that name already exists
+ KexiDB::SchemaData tmp_sdata;
+ tristate result = project()->dbConnection()->loadObjectSchemaData(
+ info->projectPartID(),
+ d->nameDialog->widget()->nameText(), tmp_sdata );
+ if (!result)
+ return false;
+ found = result==true;
+ if (found) {
+ if (allowOverwriting) {
+ int res = KMessageBox::warningYesNoCancel(this,
+ "<p>"+part->i18nMessage("Object \"%1\" already exists.", 0)
+ .arg(d->nameDialog->widget()->nameText())
+ +"</p><p>"+i18n("Do you want to replace it?")+"</p>", 0,
+ KGuiItem(i18n("&Replace"), "button_yes"),
+ KGuiItem(i18n("&Choose Other Name...")),
+ QString::null, KMessageBox::Notify|KMessageBox::Dangerous);
+ if (res == KMessageBox::No)
+ continue;
+ else if (res == KMessageBox::Cancel)
+ return cancelled;
+ else {//yes
+ allowOverwriting = true;
+ break;
+ }
+ }
+ else {
+ KMessageBox::information(this,
+ "<p>"+part->i18nMessage("Object \"%1\" already exists.", 0)
+ .arg(d->nameDialog->widget()->nameText())
+ +"</p><p>"+i18n("Please choose other name.")+"</p>");
+// " For example: Table \"my_table\" already exists" ,
+// "%1 \"%2\" already exists.\nPlease choose other name.")
+// .arg(dlg->part()->instanceName()).arg(d->nameDialog->widget()->nameText()));
+ continue;
+ }
+ }
+ }
+ while (found);
+
+ //update name and caption
+ partItem->setName( d->nameDialog->widget()->nameText() );
+ partItem->setCaption( d->nameDialog->widget()->captionText() );
+ return true;
+}
+
+tristate KexiMainWindowImpl::saveObject( KexiDialogBase *dlg, const QString& messageWhenAskingForName,
+ bool dontAsk)
+{
+ tristate res;
+ if (!dlg->neverSaved()) {
+ //data was saved in the past -just save again
+ res = dlg->storeData(dontAsk);
+ if (!res)
+ showErrorMessage(i18n("Saving \"%1\" object failed.").arg(dlg->partItem()->name()),
+ d->curDialog);
+ return res;
+ }
+
+ const int oldItemID = dlg->partItem()->identifier();
+
+ bool allowOverwriting = false;
+ res = getNewObjectInfo( dlg->partItem(), dlg->part(), allowOverwriting,
+ messageWhenAskingForName );
+ if (res != true)
+ return res;
+
+ res = dlg->storeNewData();
+ if (~res)
+ return cancelled;
+ if (!res) {
+ showErrorMessage(i18n("Saving new \"%1\" object failed.").arg(dlg->partItem()->name()),
+ d->curDialog);
+ return false;
+ }
+
+ //update navigator
+//this is alreday done in KexiProject::addStoredItem(): d->nav->addItem(dlg->partItem());
+ //item id changed to final one: update association in dialogs' dictionary
+// d->dialogs.take(oldItemID);
+ d->updateDialogId(dlg, oldItemID);
+ invalidateProjectWideActions();
+ return true;
+}
+
+tristate KexiMainWindowImpl::closeDialog(KexiDialogBase *dlg)
+{
+ return closeDialog(dlg, true);
+}
+
+tristate KexiMainWindowImpl::closeDialog(KexiDialogBase *dlg, bool layoutTaskBar, bool doNotSaveChanges)
+{
+ if (!dlg)
+ return true;
+ if (d->insideCloseDialog)
+ return true;
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->addItemToPendingDialogs(dlg->partItem(), Private::DialogClosingJob);
+#endif
+
+ d->insideCloseDialog = true;
+
+ if (dlg == d->curDialog && !dlg->isAttached()) {
+ if (d->propEditor) {
+ // ah, closing detached window - better switch off property buffer right now...
+ d->propBuffer = 0;
+ d->propEditor->editor()->changeSet( 0, false );
+ }
+ }
+
+ bool remove_on_closing = dlg->partItem() ? dlg->partItem()->neverSaved() : false;
+ if (dlg->dirty() && !d->forceDialogClosing && !doNotSaveChanges) {
+ //more accurate tool tips and what's this
+ KGuiItem saveChanges( KStdGuiItem::save() );
+ saveChanges.setToolTip(i18n("Save changes"));
+ saveChanges.setWhatsThis(
+ i18n( "Pressing this button will save all recent changes made in \"%1\" object." )
+ .arg(dlg->partItem()->name()) );
+ KGuiItem discardChanges( KStdGuiItem::discard() );
+ discardChanges.setWhatsThis(
+ i18n( "Pressing this button will discard all recent changes made in \"%1\" object." )
+ .arg(dlg->partItem()->name()) );
+
+ //dialog's data is dirty:
+ //--adidional message, e.g. table designer will return
+ // "Note: This table is already filled with data which will be removed."
+ // if the dlg is in design view mode.
+ QString additionalMessage = dlg->part()->i18nMessage(
+ ":additional message before saving design", dlg);
+ if (additionalMessage.startsWith(":"))
+ additionalMessage = QString::null;
+ if (!additionalMessage.isEmpty())
+ additionalMessage = "<p>"+additionalMessage+"</p>";
+
+ const int questionRes = KMessageBox::warningYesNoCancel( this,
+ "<p>"+dlg->part()->i18nMessage("Design of object \"%1\" has been modified.", dlg)
+ .arg(dlg->partItem()->name())+"</p><p>"+i18n("Do you want to save changes?")+"</p>"
+ + additionalMessage /*may be empty*/,
+ QString::null,
+ saveChanges,
+ discardChanges);
+ if (questionRes==KMessageBox::Cancel) {
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog(dlg->id());
+#endif
+ d->insideCloseDialog = false;
+ d->windowsToClose.clear(); //give up with 'close all'
+ return cancelled;
+ }
+ if (questionRes==KMessageBox::Yes) {
+ //save it
+// if (!dlg->storeData())
+ tristate res = saveObject( dlg, QString::null, true /*dontAsk*/ );
+ if (!res || ~res) {
+//js:TODO show error info; (retry/ignore/cancel)
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog(dlg->id());
+#endif
+ d->insideCloseDialog = false;
+ d->windowsToClose.clear(); //give up with 'close all'
+ return res;
+ }
+ remove_on_closing = false;
+ }
+ }
+
+ const int dlg_id = dlg->id(); //remember now, because removeObject() can destruct partitem object
+
+ if (remove_on_closing) {
+ //we won't save this object, and it was never saved -remove it
+ if (!removeObject( dlg->partItem(), true )) {
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog(dlg->id());
+#endif
+ //msg?
+ //TODO: ask if we'd continue and return true/false
+ d->insideCloseDialog = false;
+ d->windowsToClose.clear(); //give up with 'close all'
+ return false;
+ }
+ }
+ else {
+ //not dirty now
+ if(d->nav)
+ d->nav->updateItemName( *dlg->partItem(), false );
+ }
+
+ d->removeDialog(dlg_id); //don't remove -KMDI will do that
+ //also remove from 'print setup dialogs' cache, if needed
+ int printedObjectID = 0;
+ if (d->pageSetupDialogItemID2dataItemID_map.contains(dlg_id))
+ printedObjectID = d->pageSetupDialogItemID2dataItemID_map[ dlg_id ];
+ d->pageSetupDialogs.take(printedObjectID);
+
+ KXMLGUIClient *client = dlg->commonGUIClient();
+ KXMLGUIClient *viewClient = dlg->guiClient();
+ if (d->curDialogGUIClient==client) {
+ d->curDialogGUIClient=0;
+ }
+ if (d->curDialogViewGUIClient==viewClient) {
+ d->curDialogViewGUIClient=0;
+ }
+ if (client) {
+ //sanity: ouch, it is not removed yet? - do it now
+ if (d->closedDialogGUIClient && d->closedDialogGUIClient!=client)
+ guiFactory()->removeClient(d->closedDialogGUIClient);
+ if (d->openedDialogsCount()==0) {//now there is no dialogs - remove client RIGHT NOW!
+ d->closedDialogGUIClient=0;
+ guiFactory()->removeClient(client);
+ }
+ else {
+ //remember this - and MAYBE remove later, if needed
+ d->closedDialogGUIClient=client;
+ }
+ }
+ if (viewClient) {
+ //sanity: ouch, it is not removed yet? - do it now
+ if (d->closedDialogViewGUIClient && d->closedDialogViewGUIClient!=viewClient)
+ guiFactory()->removeClient(d->closedDialogViewGUIClient);
+ if (d->openedDialogsCount()==0) {//now there is no dialogs - remove client RIGHT NOW!
+ d->closedDialogViewGUIClient=0;
+ guiFactory()->removeClient(viewClient);
+ }
+ else {
+ //remember this - and MAYBE remove later, if needed
+ d->closedDialogViewGUIClient=viewClient;
+ }
+ }
+
+ const bool isInMaximizedChildFrmMode = this->isInMaximizedChildFrmMode();
+
+ KMdiMainFrm::closeWindow(dlg, layoutTaskBar);
+
+ //focus navigator if nothing else available
+ if (d->openedDialogsCount()==0) {
+ d->maximizeFirstOpenedChildFrm = isInMaximizedChildFrmMode;
+ if (d->nav)
+ d->nav->setFocus();
+ d->updatePropEditorVisibility(0);
+ }
+
+ invalidateActions();
+ d->insideCloseDialog = false;
+ if (!d->windowsToClose.isEmpty()) //continue 'close all'
+ closeDialog(d->windowsToClose.take(0), true);
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog( dlg_id );
+
+ //perform pending global action that was suspended:
+ if (!d->pendingDialogsExist()) {
+ d->executeActionWhenPendingJobsAreFinished();
+ }
+#endif
+ return true;
+}
+
+void KexiMainWindowImpl::detachWindow(KMdiChildView *pWnd,bool bShow)
+{
+ KMdiMainFrm::detachWindow(pWnd,bShow);
+ // update icon - from small to large
+ pWnd->setIcon( DesktopIcon( static_cast<KexiDialogBase *>(pWnd)->itemIcon() ) );
+// pWnd->setIcon( DesktopIcon( static_cast<KexiDialogBase *>(pWnd)->part()->info()->itemIcon() ) );
+ if (dynamic_cast<KexiDialogBase*>(pWnd))
+ dynamic_cast<KexiDialogBase*>(pWnd)->sendDetachedStateToCurrentView();
+}
+
+void KexiMainWindowImpl::attachWindow(KMdiChildView *pWnd, bool /*bShow*/, bool bAutomaticResize)
+{
+// if (bAutomaticResize || w->size().isEmpty() || (w->size() == QSize(1,1))) {
+ KMdiMainFrm::attachWindow(pWnd,true,bAutomaticResize);
+ //for dialogs in normal state: decrease dialog's height if it exceeds area contents
+ if (pWnd->mdiParent()->state() == KMdiChildFrm::Normal
+ && pWnd->geometry().bottom() > pWnd->mdiParent()->mdiAreaContentsRect().bottom())
+ {
+ QRect r = pWnd->geometry();
+ r.setBottom( pWnd->mdiParent()->mdiAreaContentsRect().bottom() - 5 );
+ pWnd->setGeometry( r );
+ }
+ // update icon - from large to small
+ pWnd->mdiParent()->setIcon( SmallIcon( static_cast<KexiDialogBase *>(pWnd)->itemIcon() ) );
+ if (dynamic_cast<KexiDialogBase*>(pWnd))
+ dynamic_cast<KexiDialogBase*>(pWnd)->sendAttachedStateToCurrentView();
+}
+
+QWidget* KexiMainWindowImpl::findWindow(QWidget *w)
+{
+ while (w && !acceptsSharedActions(w))
+ w = w->parentWidget();
+ return w;
+}
+
+bool KexiMainWindowImpl::acceptsSharedActions(QObject *w)
+{
+ return w->inherits("KexiDialogBase") || w->inherits("KexiViewBase");
+}
+
+bool KexiMainWindowImpl::eventFilter( QObject *obj, QEvent * e )
+{
+ //KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name()<<endl;
+ if (e->type()==QEvent::KeyPress) {
+ KexiVDebug << "KEY EVENT " << QString::number(static_cast<QKeyEvent*>(e)->key(), 16) << endl;
+ KexiVDebug << endl;
+ }
+ if (e->type()==QEvent::AccelOverride) {
+ //KexiVDebug << "AccelOverride EVENT " << static_cast<QKeyEvent*>(e)->key() << " " << static_cast<QKeyEvent*>(e)->state() == ControlButton << endl;
+
+ //avoid sending CTRL+Tab key twice for tabbed/ideal mode, epecially for win32
+ if (static_cast<QKeyEvent*>(e)->key()==Qt::Key_Tab && static_cast<QKeyEvent*>(e)->state() == ControlButton) {
+ if (d->action_window_next->shortcut().keyCodeQt()==Qt::Key_Tab+Qt::CTRL && d->action_window_next->shortcut().count()==1
+ && (mdiMode()==KMdi::TabPageMode || mdiMode()==KMdi::IDEAlMode))
+ {
+ static_cast<QKeyEvent*>(e)->accept();
+ }
+ }
+ }
+ if (e->type()==QEvent::Close) {
+ KexiVDebug << "Close EVENT" << endl;
+ }
+ if (e->type()==QEvent::Resize) {
+ KexiVDebug << "Resize EVENT" << endl;
+ }
+ if (e->type()==QEvent::ShowMaximized) {
+ KexiVDebug << "ShowMaximized EVENT" << endl;
+ }
+
+/* if (obj==d->propEditor) {
+ if (e->type()==QEvent::Resize) {
+ d->updatePropEditorDockWidthInfo();
+ }
+ }*/
+
+ QWidget *focus_w = 0;
+ if (obj->inherits("QPopupMenu")) {
+ /* Fixes for popup menus behaviour:
+ For hiding/showing: focus previously (d->focus_before_popup)
+ focused window, if known, otherwise focus currently focused one.
+ And: just invalidate actions.
+ */
+ if (e->type()==QEvent::Hide || e->type()==QEvent::Show) {
+ KexiVDebug << e->type() << endl;
+ focus_w = focusWindow();
+ if (!d->focus_before_popup.isNull()) {
+ d->focus_before_popup->setFocus();
+ d->focus_before_popup=0;
+ invalidateSharedActions();
+ } else {
+ if (focus_w) {
+ focus_w->setFocus();
+ invalidateSharedActions();
+ }
+ }
+ }
+ return false;
+ }
+
+ /*! On mouse click on the findow, make sure it's focused and actions are invalidated */
+ if (e->type()==QEvent::MouseButtonPress) {
+ QWidget *w = findWindow(static_cast<QWidget*>(obj));
+ KexiVDebug << "MouseButtonPress EVENT " << (w ? w->name() : 0) << endl;
+ if (w) {
+ w->setFocus();
+ invalidateSharedActions(d->curDialog);
+ }
+ }
+ QWidget *w = findWindow(static_cast<QWidget*>(obj));
+ if (e->type()==QEvent::FocusIn) {
+ focus_w = focusWindow();
+ KexiVDebug << "Focus EVENT" << endl;
+ KexiVDebug << (focus_w ? focus_w->name() : "" ) << endl;
+ KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name() <<endl;
+#ifdef KEXI_STATUSBAR_DEBUG
+ QWidget *focus_widget = focus_w ? focus_w->focusWidget() : 0;
+ d->statusBar->setStatus(QString("FOCUS VIEW: %1 %2, FOCUS WIDGET: %3 %4")
+ .arg(focus_w ? focus_w->className() : "").arg(focus_w ? focus_w->name() : "")
+ .arg(focus_widget ? focus_widget->className() : "").arg(focus_widget ? focus_widget->name() : "")
+ );
+#endif
+ }
+ else if (e->type()==QEvent::FocusOut) {
+ focus_w = focusWindow();
+ KexiVDebug << "Focus OUT EVENT" << endl;
+ KexiVDebug << (focus_w ? focus_w->name() : "" ) << endl;
+ KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name() <<endl;
+#ifdef KEXI_STATUSBAR_DEBUG
+ QWidget *focus_widget = focus_w ? focus_w->focusWidget() : 0;
+ d->statusBar->setStatus(QString("FOCUS VIEW: %1 %2, FOCUS WIDGET: %3 %4")
+ .arg(focus_w ? focus_w->className() : "").arg(focus_w ? focus_w->name() : "")
+ .arg(focus_widget ? focus_widget->className() : "").arg(focus_widget ? focus_widget->name() : "")
+ );
+#endif
+ }
+ if (e->type()==QEvent::WindowActivate) {
+ KexiVDebug << "WindowActivate EVENT" << endl;
+ KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name()<<endl;
+ }
+#if 0
+ if (e->type()==QEvent::FocusIn) {
+ if (focus_w) {
+// if (d->actionProxies[ w ])
+// if (d->actionProxies[ focus_w ]) {
+ if (actionProxyFor( focus_w )) {
+// invalidateSharedActions();
+ }
+ else {
+/* QObject* o = focusWidget();
+ while (o && !o->inherits("KexiDialogBase") && !o->inherits("KexiDockBase"))
+ o = o->parent();*/
+//js invalidateSharedActions(focus_w);
+ }
+ }
+// /*|| e->type()==QEvent::FocusOut*/) && /*(!obj->inherits("KexiDialogBase")) &&*/ d->actionProxies[ obj ]) {
+// invalidateSharedActions();
+ }
+ if (e->type()==QEvent::FocusOut && focus_w && focus_w==d->curDialog && actionProxyFor( obj )) {
+ invalidateSharedActions(d->curDialog);
+ }
+#endif
+
+ if (!d->focus_before_popup.isNull() && e->type()==QEvent::FocusOut && obj->inherits("KMenuBar")) {
+ //d->nav->setFocus();
+ d->focus_before_popup->setFocus();
+ d->focus_before_popup=0;
+ invalidateSharedActions(d->curDialog);
+ return true;
+ }
+
+ //remember currently focued window invalidate act.
+ if (e->type()==QEvent::FocusOut) {
+ if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Popup) {
+ if (KexiUtils::hasParent(d->curDialog, focus_w)) {
+ invalidateSharedActions(d->curDialog);
+ d->focus_before_popup=d->curDialog;
+ }
+ else {
+//not needed??? invalidateSharedActions(focus_w);
+ d->focus_before_popup=focus_w;
+ }
+ }
+ }
+
+ //keep focus in main window:
+ if (w && w==d->nav) {
+// kdDebug() << "NAV" << endl;
+ if (e->type()==QEvent::FocusIn) {
+ return true;
+ } else if (e->type()==QEvent::WindowActivate && w==d->focus_before_popup) {
+// d->nav->setFocus();
+ d->focus_before_popup=0;
+ return true;
+ } else if (e->type()==QEvent::FocusOut) {
+ if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Tab) {
+ //activate current child:
+ if (d->curDialog) {
+ d->curDialog->activate();
+ return true;
+ }
+ }
+ else if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Popup) {
+ d->focus_before_popup=w;
+ }
+ //invalidateSharedActions();
+ } else if (e->type()==QEvent::Hide) {
+ setFocus();
+ return false;
+ }
+ }
+ if (d->block_KMdiMainFrm_eventFilter)//we don't want KMDI to eat our event!
+ return false;
+ return KMdiMainFrm::eventFilter(obj,e);//let KMDI do its work
+}
+
+bool KexiMainWindowImpl::openingAllowed(KexiPart::Item* item, int viewMode)
+{
+ //! @todo this can be more complex once we deliver ACLs...
+ if (!userMode())
+ return true;
+ KexiPart::Part * part = Kexi::partManager().partForMimeType(item->mimeType());
+ return part && (part->supportedUserViewModes() & viewMode);
+}
+
+KexiDialogBase *
+KexiMainWindowImpl::openObject(const QCString& mimeType, const QString& name,
+ int viewMode, bool &openingCancelled, QMap<QString,QString>* staticObjectArgs)
+{
+ KexiPart::Item *item = d->prj->itemForMimeType(mimeType,name);
+ if (!item)
+ return 0;
+ return openObject(item, viewMode, openingCancelled, staticObjectArgs);
+}
+
+KexiDialogBase *
+KexiMainWindowImpl::openObject(KexiPart::Item* item, int viewMode, bool &openingCancelled,
+ QMap<QString,QString>* staticObjectArgs, QString* errorMessage)
+{
+ if (!openingAllowed(item, viewMode)) {
+ if (errorMessage)
+ *errorMessage = i18n("opening is not allowed in \"data view/design view/text view\" mode",
+ "opening is not allowed in \"%1\" mode").arg(Kexi::nameForViewMode(viewMode));
+ openingCancelled = true;
+ return 0;
+ }
+
+ if (!d->prj || !item)
+ return 0;
+ KexiUtils::WaitCursor wait;
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
+ if (pendingType != Private::NoJob) {
+ openingCancelled = true;
+ return 0;
+ }
+#else
+ KexiDialogBase *dlg = d->openedDialogFor( item );
+#endif
+ openingCancelled = false;
+
+ bool needsUpdateViewGUIClient = true;
+ if (dlg) {
+ dlg->activate();
+ if (viewMode!=dlg->currentViewMode()) {
+ if (!switchToViewMode(viewMode))
+ return 0;
+ }
+ needsUpdateViewGUIClient = false;
+ }
+ else {
+ d->updatePropEditorVisibility(viewMode);
+ KexiPart::Part *part = Kexi::partManager().partForMimeType(item->mimeType());
+ //update tabs before opening
+ updateCustomPropertyPanelTabs(d->curDialog ? d->curDialog->part() : 0,
+ d->curDialog ? d->curDialog->currentViewMode() : Kexi::NoViewMode,
+ part, viewMode);
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->addItemToPendingDialogs(item, Private::DialogOpeningJob);
+#endif
+ dlg = d->prj->openObject(this, *item, viewMode, staticObjectArgs);
+ }
+
+ if (!dlg || !activateWindow(dlg)) {
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog(item->identifier());
+#endif
+ updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert
+ //js TODO: add error msg...
+ return 0;
+ }
+
+ if (needsUpdateViewGUIClient /*&& !userMode()*/) {
+ //view changed: switch to this view's gui client
+ KXMLGUIClient *viewClient=dlg->guiClient();
+ updateDialogViewGUIClient(viewClient);
+ if (d->curDialogViewGUIClient && !viewClient)
+ guiFactory()->removeClient(d->curDialogViewGUIClient);
+ d->curDialogViewGUIClient=viewClient; //remember
+ }
+
+ invalidateViewModeActions();
+ if (viewMode!=dlg->currentViewMode())
+ invalidateSharedActions();
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ d->removePendingDialog( dlg->id() );
+
+ //perform pending global action that was suspended:
+ if (!d->pendingDialogsExist()) {
+ d->executeActionWhenPendingJobsAreFinished();
+ }
+#endif
+ return dlg;
+}
+
+KexiDialogBase *
+KexiMainWindowImpl::openObjectFromNavigator(KexiPart::Item* item, int viewMode)
+{
+ bool openingCancelled;
+ return openObjectFromNavigator(item, viewMode, openingCancelled);
+}
+
+KexiDialogBase *
+KexiMainWindowImpl::openObjectFromNavigator(KexiPart::Item* item, int viewMode,
+ bool &openingCancelled)
+{
+ if (!openingAllowed(item, viewMode)) {
+ openingCancelled = true;
+ return 0;
+ }
+ if (!d->prj || !item)
+ return false;
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
+ if (pendingType!=Private::NoJob) {
+ openingCancelled = true;
+ return 0;
+ }
+#else
+ KexiDialogBase *dlg = d->openedDialogFor( item );
+#endif
+ openingCancelled = false;
+ if (dlg) {
+ if (activateWindow(dlg)) {//item->identifier())) {//just activate
+ invalidateViewModeActions();
+ return dlg;
+ }
+ }
+ //if DataViewMode is not supported, try Design, then Text mode (currently useful for script part)
+ KexiPart::Part *part = Kexi::partManager().partForMimeType(item->mimeType());
+ if (!part)
+ return 0;
+ if (viewMode == Kexi::DataViewMode && !(part->supportedViewModes() & Kexi::DataViewMode)) {
+ if (part->supportedViewModes() & Kexi::DesignViewMode)
+ return openObjectFromNavigator( item, Kexi::DesignViewMode, openingCancelled );
+ else if (part->supportedViewModes() & Kexi::TextViewMode)
+ return openObjectFromNavigator( item, Kexi::TextViewMode, openingCancelled );
+ }
+ //do the same as in openObject()
+ return openObject(item, viewMode, openingCancelled);
+}
+
+tristate KexiMainWindowImpl::closeObject(KexiPart::Item* item)
+{
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
+ if (pendingType == Private::DialogClosingJob)
+ return true;
+ else if (pendingType == Private::DialogOpeningJob)
+ return cancelled;
+#else
+ KexiDialogBase *dlg = d->openedDialogFor( item );
+#endif
+ if (!dlg)
+ return cancelled;
+ return closeDialog(dlg);
+}
+
+bool KexiMainWindowImpl::newObject( KexiPart::Info *info, bool& openingCancelled )
+{
+ if (userMode()) {
+ openingCancelled = true;
+ return false;
+ }
+ openingCancelled = false;
+ if (!d->prj || !info)
+ return false;
+ KexiPart::Part *part = Kexi::partManager().partForMimeType(info->mimeType());
+ if(!part)
+ return false;
+
+#ifdef KEXI_ADD_CUSTOM_OBJECT_CREATION
+# include "keximainwindowimpl_customobjcreation.h"
+#endif
+
+ KexiPart::Item *it = d->prj->createPartItem(info); //this, *item, viewMode);
+ if (!it) {
+ //js: todo: err
+ return false;
+ }
+
+ if (!it->neverSaved()) //only add stored objects to the browser
+ d->nav->addItem(*it);
+ return openObject(it, Kexi::DesignViewMode, openingCancelled);
+}
+
+tristate KexiMainWindowImpl::removeObject( KexiPart::Item *item, bool dontAsk )
+{
+ if (userMode())
+ return cancelled;
+ if (!d->prj || !item)
+ return false;
+
+ KexiPart::Part *part = Kexi::partManager().partForMimeType(item->mimeType());
+ if (!part)
+ return false;
+
+ if (!dontAsk) {
+ if (KMessageBox::No == KMessageBox::warningYesNo(this,
+ "<p>"+i18n("Do you want to permanently delete:\n"
+ "%1\n"
+ "If you click \"Delete\", you will not be able to undo the deletion.")
+ .arg( "</p><p>"+part->instanceCaption()+" \""+ item->name() + "\"?</p>" ),
+ 0, KGuiItem(i18n("Delete"), "editdelete"), KStdGuiItem::no()))
+ return cancelled;
+ }
+
+ //also close 'print setup' dialog for this item, if any
+ tristate res;
+// int printedObjectID = 0;
+// if (d->pageSetupDialogItemID2dataItemID_map.contains(item->identifier()))
+// printedObjectID = d->pageSetupDialogItemID2dataItemID_map[ item->identifier() ];
+ KexiDialogBase * pageSetupDlg = d->pageSetupDialogs[ item->identifier() ];
+ const bool oldInsideCloseDialog = d->insideCloseDialog;
+ d->insideCloseDialog = false;
+ res = closeDialog(pageSetupDlg);
+ d->insideCloseDialog = oldInsideCloseDialog;
+ if (!res || ~res) {
+ return res;
+ }
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
+ if (pendingType!=Private::NoJob) {
+ return cancelled;
+ }
+#else
+ KexiDialogBase *dlg = d->openedDialogFor( item );
+#endif
+
+ if (dlg) {//close existing window
+// if (!dlg->tryClose(true))
+ const bool tmp = d->forceDialogClosing;
+ /*const bool remove_on_closing = */dlg->partItem()->neverSaved();
+ d->forceDialogClosing = true;
+ res = closeDialog(dlg);
+ d->forceDialogClosing = tmp; //restore
+ if (!res || ~res) {
+ return res;
+ }
+// if (remove_on_closing) //already removed
+ // return true;
+// if (!dlg->close(true))
+// return true; //ok - close cancelled
+ }
+
+ //in case the dialog is a 'print setup' dialog, also update d->pageSetupDialogs
+ int dataItemID = d->pageSetupDialogItemID2dataItemID_map[item->identifier()];
+ d->pageSetupDialogItemID2dataItemID_map.remove(item->identifier());
+ d->pageSetupDialogs.take( dataItemID );
+
+ if (!d->prj->removeObject(this, *item)) {
+ //TODO(js) better msg
+ showSorryMessage( i18n("Could not remove object.") );
+ return false;
+ }
+ return true;
+}
+
+void KexiMainWindowImpl::renameObject( KexiPart::Item *item, const QString& _newName, bool &success )
+{
+ if (userMode()) {
+ success = false;
+ return;
+ }
+ d->pendingDialogsExist();
+ QString newName = _newName.stripWhiteSpace();
+ if (newName.isEmpty()) {
+ showSorryMessage( i18n("Could not set empty name for this object.") );
+ success = false;
+ return;
+ }
+ enableMessages(false); //to avoid double messages
+ const bool res = d->prj->renameObject(this, *item, newName);
+ enableMessages(true);
+ if (!res) {
+ showErrorMessage( d->prj, i18n("Renaming object \"%1\" failed.").arg(newName) );
+ success = false;
+ return;
+ }
+ d->pendingDialogsExist();
+}
+
+void KexiMainWindowImpl::slotObjectRenamed(const KexiPart::Item &item, const QCString& /*oldName*/)
+{
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ KexiDialogBase *dlg = d->openedDialogFor( &item, pendingType );
+ if (pendingType!=Private::NoJob)
+ return;
+#else
+ KexiDialogBase *dlg = d->openedDialogFor( &item );
+#endif
+ if (!dlg)
+ return;
+
+ //change item
+ dlg->updateCaption();
+ if (static_cast<KexiDialogBase*>(d->curDialog)==dlg)//optionally, update app. caption
+ updateAppCaption();
+}
+
+int KexiMainWindowImpl::generatePrivateID()
+{
+ return --d->privateIDCounter;
+}
+
+void KexiMainWindowImpl::acceptPropertySetEditing()
+{
+ if (d->propEditor)
+ d->propEditor->editor()->acceptInput();
+}
+
+void KexiMainWindowImpl::propertySetSwitched(KexiDialogBase *dlg, bool force,
+ bool preservePrevSelection, const QCString& propertyToSelect)
+{
+ kdDebug() << "KexiMainWindowImpl::propertySetSwitched() d->curDialog: "
+ << (d->curDialog ? d->curDialog->caption() : QString("NULL")) << " dlg: " << (dlg ? dlg->caption() : QString("NULL"))<< endl;
+ if ((KexiDialogBase*)d->curDialog!=dlg) {
+ d->propBuffer = 0; //we'll need to move to another prop. set
+ return;
+ }
+ if (d->propEditor) {
+ KoProperty::Set *newBuf = d->curDialog ? d->curDialog->propertySet() : 0;
+ if (!newBuf || (force || static_cast<KoProperty::Set*>(d->propBuffer) != newBuf)) {
+ d->propBuffer = newBuf;
+ if (preservePrevSelection) {
+ if (propertyToSelect.isEmpty())
+ d->propEditor->editor()->changeSet( d->propBuffer, preservePrevSelection );
+ else
+ d->propEditor->editor()->changeSet( d->propBuffer, propertyToSelect );
+ }
+ }
+ }
+}
+
+void KexiMainWindowImpl::slotDirtyFlagChanged(KexiDialogBase* dlg)
+{
+ KexiPart::Item *item = dlg->partItem();
+ //update text in navigator and app. caption
+ if(!userMode())
+ d->nav->updateItemName( *item, dlg->dirty() );
+
+ invalidateActions();
+ updateAppCaption();
+}
+
+void KexiMainWindowImpl::slotMdiModeHasBeenChangedTo(KMdi::MdiMode)
+{
+ //after switching to other MDI mode, pointer to current dialog needs to be updated
+ activateFirstWin();
+ activeWindowChanged(activeWindow());
+}
+
+void KexiMainWindowImpl::slotTipOfTheDay()
+{
+ //todo
+}
+
+void KexiMainWindowImpl::slotImportantInfo()
+{
+ importantInfo(false);
+}
+
+void KexiMainWindowImpl::slotStartFeedbackAgent()
+{
+#ifndef KEXI_NO_FEEDBACK_AGENT
+#ifdef FEEDBACK_CLASS
+ const KAboutData* about = KApplication::kApplication()->aboutData();
+ FEEDBACK_CLASS* wizard = new FEEDBACK_CLASS( about->programName(),
+ about->version(), 0, 0, 0, FEEDBACK_CLASS::AllPages );
+
+ if ( wizard->exec() )
+ {
+ KApplication::kApplication()->invokeMailer( "kexi-reports-dummy@kexi.org",
+ QString::null, QString::null,
+ about->appName() + QCString( " [feedback]" ),
+ wizard->feedbackDocument().toString( 2 ).local8Bit() );
+ }
+
+ delete wizard;
+#endif
+#endif
+}
+
+void KexiMainWindowImpl::importantInfo(bool /*onStartup*/)
+{
+#if 0
+ if (onStartup && !d->showImportantInfoOnStartup)
+ return;
+
+ QString key = QString("showImportantInfo %1").arg(KEXI_VERSION_STRING);
+ d->config->setGroup("Startup");
+ bool show = d->config->readBoolEntry(key,true);
+
+ if (show || !onStartup) { //if !onStartup - dialog is always shown
+ d->config->setGroup("TipOfDay");
+ if (!d->config->hasKey("RunOnStart"))
+ d->config->writeEntry("RunOnStart",true);
+
+ QString lang = KGlobal::locale()->language();
+ QString fname = locate("data", QString("kexi/readme_")+lang);
+ if (fname.isEmpty())//back to default
+ fname = locate("data", "kexi/readme_en");
+ KTipDialog tipDialog(new KTipDatabase(QString::null), 0);
+ tipDialog.setCaption(i18n("Important Information"));
+ QObjectList *l = tipDialog.queryList( "KPushButton" );//hack: hide <- -> buttons
+ int i=0;
+ for (QObjectListIt it( *l ); it.current() && i<2; ++it, i++ )
+ static_cast<KPushButton*>(it.current())->hide();
+ QFile f(fname);
+ if ( f.open( IO_ReadOnly ) ) {
+ QTextStream ts(&f);
+ ts.setCodec( KGlobal::locale()->codecForEncoding() );
+ QTextBrowser *tb = KexiUtils::findFirstChild<KTextBrowser>(&tipDialog,"KTextBrowser");
+ if (tb) {
+ tb->setText( QString("<qt>%1</qt>").arg(ts.read()) );
+ }
+ f.close();
+ }
+
+ tipDialog.adjustSize();
+ QRect desk = QApplication::desktop()->screenGeometry( QApplication::desktop()->screenNumber(this) );
+ tipDialog.resize( QMAX(tipDialog.width(),desk.width()*3/5), QMAX(tipDialog.height(),desk.height()*3/5) );
+ KDialog::centerOnScreen(&tipDialog);
+ tipDialog.setModal ( true );
+ tipDialog.exec();
+ //a hack: get user's settings
+ d->config->setGroup("TipOfDay");
+ show = d->config->readBoolEntry("RunOnStart", show);
+ }
+
+ //write our settings back
+ d->config->setGroup("Startup");
+ d->config->writeEntry(key,show);
+ d->showImportantInfoOnStartup = false;
+#endif
+}
+
+void KexiMainWindowImpl::slotOptionsEnableForms(bool show, bool noMessage)
+{
+ Q_UNUSED(noMessage);
+ Kexi::tempShowForms() = show;
+}
+
+bool KexiMainWindowImpl::userMode() const
+{
+ return d->userMode;
+}
+
+bool
+KexiMainWindowImpl::initUserMode(KexiProjectData *projectData)
+{
+// Kexi::tempShowForms() = true;
+// Kexi::tempShowReports() = true;
+// Kexi::tempShowMacros() = true;
+// Kexi::tempShowScripts() = true;
+ if(!projectData)
+ return false;
+
+ createKexiProject(projectData); //initialize project
+// d->prj->setFinal(true); //announce that we are in fianl mode
+
+ tristate res = d->prj->open(); //try to open database
+ if (!res || ~res) {
+ delete d->prj;
+ d->prj = 0;
+ return false;
+ }
+
+#if 0 //todo reenable; autoopen objects are handled elsewhere
+ KexiDB::TableSchema *sch = d->prj->dbConnection()->tableSchema("kexi__final");
+ QString err_msg = i18n("Could not start project \"%1\" in Final Mode.")
+ .arg(static_cast<KexiDB::SchemaData*>(projectData)->name());
+ if(!sch)
+ {
+ hide();
+ showErrorMessage( err_msg, i18n("No Final Mode data found.") );
+ return false;
+ }
+
+ KexiDB::Cursor *c = d->prj->dbConnection()->executeQuery(*sch);
+ if(!c)
+ {
+ hide();
+ showErrorMessage( err_msg, i18n("Error reading Final Mode data.") );
+ return false;
+ }
+
+ QString startupPart;
+ QString startupItem;
+ while(c->moveNext())
+ {
+ kdDebug() << "KexiMainWinImpl::initFinalMode(): property: [" << c->value(1).toString() << "] " << c->value(2).toString() << endl;
+ if(c->value(1).toString() == "startup-part")
+ startupPart = c->value(2).toString();
+ else if(c->value(1).toString() == "startup-item")
+ startupItem = c->value(2).toString();
+ else if(c->value(1).toString() == "mainxmlui")
+ setXML(c->value(2).toString());
+ }
+ d->prj->dbConnection()->deleteCursor(c);
+
+ kdDebug() << "KexiMainWinImpl::initFinalMode(): part: " << startupPart << endl;
+ kdDebug() << "KexiMainWinImpl::initFinalMode(): item: " << startupItem << endl;
+
+ initActions();
+ initUserActions();
+ guiFactory()->addClient(this);
+ setStandardToolBarMenuEnabled(false);
+ setHelpMenuEnabled(false);
+
+ KexiPart::Info *i = Kexi::partManager().infoForMimeType(startupPart.latin1());
+ if (!i) {
+ hide();
+ showErrorMessage( err_msg, i18n("Specified plugin does not exist.") );
+ return false;
+ }
+
+ Kexi::partManager().part(i);
+ KexiPart::Item *item = d->prj->item(i, startupItem);
+ bool openingCancelled;
+ if(!openObject(item, Kexi::DataViewMode, openingCancelled) && !openingCancelled) {
+ hide();
+ showErrorMessage( err_msg, i18n("Specified object could not be opened.") );
+ return false;
+ }
+
+ QWidget::setCaption("MyApp");//TODO
+#endif
+ return true;
+}
+
+void
+KexiMainWindowImpl::initUserActions()
+{
+#if 0 //unused for now
+ KexiDB::Cursor *c = d->prj->dbConnection()->executeQuery("SELECT p_id, name, text, icon, method, arguments FROM kexi__useractions WHERE scope = 0");
+ if(!c)
+ return;
+
+ while(c->moveNext())
+ {
+ KexiUserAction::fromCurrentRecord(this, actionCollection(), c);
+ }
+ d->prj->dbConnection()->deleteCursor(c);
+/*
+ KexiUserAction *a1 = new KexiUserAction(this, actionCollection(), "user_dataview", "Change to dataview", "table");
+ Arguments args;
+ args.append(QVariant("kexi/table"));
+ args.append(QVariant("persons"));
+ a1->setMethod(KexiUserAction::OpenObject, args);
+*/
+#endif
+}
+
+void KexiMainWindowImpl::slotToolsProjectMigration()
+{
+ showProjectMigrationWizard(QString::null, QString::null);
+}
+
+void KexiMainWindowImpl::slotToolsCompactDatabase()
+{
+ KexiProjectData *data = 0;
+ KexiDB::Driver *drv = 0;
+ const bool projectWasOpened = d->prj;
+
+ if (!d->prj) {
+ KexiStartupDialog dlg(
+ KexiStartupDialog::OpenExisting, 0, Kexi::connset(), Kexi::recentProjects(),
+ this, "KexiOpenDialog");
+
+ if (dlg.exec()!=QDialog::Accepted)
+ return;
+
+ if (dlg.selectedFileName().isEmpty()) {
+//! @todo add support for server based if needed?
+ return;
+ }
+ KexiDB::ConnectionData cdata;
+ cdata.setFileName( dlg.selectedFileName() );
+
+ //detect driver name for the selected file
+ KexiStartupData::Import detectedImportAction;
+ tristate res = KexiStartupHandler::detectActionForFile(
+ detectedImportAction, cdata.driverName,
+ "" /*suggestedDriverName*/, cdata.fileName(), 0,
+ KexiStartupHandler::SkipMessages | KexiStartupHandler::ThisIsAProjectFile
+ | KexiStartupHandler::DontConvert);
+
+ if (true==res && !detectedImportAction)
+ drv = Kexi::driverManager().driver( cdata.driverName );
+ if (!drv || !(drv->features() & KexiDB::Driver::CompactingDatabaseSupported)) {
+ KMessageBox::information(this, "<qt>"+
+ i18n("Compacting database file <nobr>\"%1\"</nobr> is not supported.")
+ .arg(QDir::convertSeparators(cdata.fileName())));
+ return;
+ }
+ data = new KexiProjectData( cdata, cdata.fileName() );
+ }
+ else {
+ //sanity
+ if ( !(d->prj && d->prj->dbConnection()
+ && (d->prj->dbConnection()->driver()->features() & KexiDB::Driver::CompactingDatabaseSupported) ))
+ return;
+
+ if (KMessageBox::Continue != KMessageBox::warningContinueCancel(this,
+ i18n("The current project has to be closed before compacting the database. "
+ "It will be open again after compacting.\n\nDo you want to continue?")))
+ return;
+
+ data = new KexiProjectData(*d->prj->data()); // a copy
+ drv = d->prj->dbConnection()->driver();
+ const tristate res = closeProject();
+ if (~res || !res)
+ return;
+ }
+
+ if (!drv->adminTools().vacuum(*data->connectionData(), data->databaseName())) {
+ //err msg
+ showErrorMessage( &drv->adminTools() );
+ }
+
+ if (data && projectWasOpened) {
+ openProject(*data);
+ delete data;
+ }
+}
+
+tristate KexiMainWindowImpl::showProjectMigrationWizard(
+ const QString& mimeType, const QString& databaseName, const KexiDB::ConnectionData *cdata)
+{
+ //pass arguments
+ QMap<QString,QString> args;
+ args.insert("mimeType", mimeType);
+ args.insert("databaseName", databaseName);
+ if (cdata) { //pass ConnectionData serialized as a string...
+ QString str;
+ KexiUtils::serializeMap( KexiDB::toMap( *cdata ), str );
+ args.insert("connectionData", str);
+ }
+
+ QDialog *dlg = KexiInternalPart::createModalDialogInstance("migration", this, this, 0, &args);
+ if (!dlg)
+ return false; //error msg has been shown by KexiInternalPart
+
+ const int result = dlg->exec();
+ delete dlg;
+ //raise();
+ if (result!=QDialog::Accepted)
+ return cancelled;
+
+ //open imported project in a new Kexi instance
+ QString destinationDatabaseName( args["destinationDatabaseName"] );
+ QString fileName, destinationConnectionShortcut, dbName;
+ if (!destinationDatabaseName.isEmpty()) {
+ if (args.contains("destinationConnectionShortcut")) {
+ // server-based
+ destinationConnectionShortcut = args["destinationConnectionShortcut"];
+ }
+ else {
+ // file-based
+ fileName = destinationDatabaseName;
+ destinationDatabaseName = QString::null;
+ }
+ tristate res = openProject(fileName, destinationConnectionShortcut,
+ destinationDatabaseName);
+ raise();
+ return res;
+// KexiDB::ConnectionData *connData = new KexiDB::ConnectionData();
+// KexiDB::fromMap( KexiUtils::deserializeMap( args["destinationConnectionData"] ), *connData );
+// return openProject(destinationFileName, 0);
+ }
+ return true;
+}
+
+tristate KexiMainWindowImpl::executeItem(KexiPart::Item* item)
+{
+ KexiPart::Info *info = item ? Kexi::partManager().infoForMimeType(item->mimeType()) : 0;
+ if ( (! info) || (! info->isExecuteSupported()) )
+ return false;
+ KexiPart::Part *part = Kexi::partManager().part(info);
+ if (!part)
+ return false;
+ return part->execute(item);
+}
+
+void KexiMainWindowImpl::slotProjectImportDataTable()
+{
+//! @todo allow data appending (it is not possible now)
+ if (userMode())
+ return;
+ QMap<QString,QString> args;
+ args.insert("sourceType", "file");
+ QDialog *dlg = KexiInternalPart::createModalDialogInstance(
+ "csv_importexport", "KexiCSVImportDialog", this, this, 0, &args);
+ if (!dlg)
+ return; //error msg has been shown by KexiInternalPart
+ dlg->exec();
+ delete dlg;
+}
+
+tristate KexiMainWindowImpl::executeCustomActionForObject(KexiPart::Item* item,
+ const QString& actionName)
+{
+ if (actionName == "exportToCSV")
+ return exportItemAsDataTable(item);
+ else if (actionName == "copyToClipboardAsCSV")
+ return copyItemToClipboardAsDataTable(item);
+
+ kexiwarn << "KexiMainWindowImpl::executeCustomActionForObject(): no such action: "
+ << actionName << endl;
+ return false;
+}
+
+tristate KexiMainWindowImpl::exportItemAsDataTable(KexiPart::Item* item)
+{
+ if (!item)
+ return false;
+//! @todo: check if changes to this are saved, if not: ask for saving
+//! @todo: accept row changes...
+
+ QMap<QString,QString> args;
+ args.insert("destinationType", "file");
+ args.insert("itemId", QString::number(item->identifier()));
+ QDialog *dlg = KexiInternalPart::createModalDialogInstance(
+ "csv_importexport", "KexiCSVExportWizard", this, this, 0, &args);
+ if (!dlg)
+ return false; //error msg has been shown by KexiInternalPart
+ int result = dlg->exec();
+ delete dlg;
+ return result == QDialog::Rejected ? cancelled : true;
+}
+
+bool KexiMainWindowImpl::printItem(KexiPart::Item* item, const QString& titleText)
+{
+ return printItem(item, KexiSimplePrintingSettings::load(), titleText);
+}
+
+tristate KexiMainWindowImpl::printItem(KexiPart::Item* item)
+{
+ return printItem(item, QString::null);
+}
+
+bool KexiMainWindowImpl::printItem(KexiPart::Item* item, const KexiSimplePrintingSettings& settings,
+ const QString& titleText)
+{
+//! @todo: check if changes to this object's design are saved, if not: ask for saving
+//! @todo: accept row changes...
+ KexiSimplePrintingCommand cmd(this, item->identifier());
+ //modal
+ return cmd.print(settings, titleText);
+}
+
+bool KexiMainWindowImpl::printPreviewForItem(KexiPart::Item* item, const QString& titleText, bool reload)
+{
+ return printPreviewForItem(item, KexiSimplePrintingSettings::load(), titleText, reload);
+}
+
+tristate KexiMainWindowImpl::printPreviewForItem(KexiPart::Item* item)
+{
+ return printPreviewForItem(item, QString::null,
+//! @todo store cached row data?
+ true/*reload*/);
+}
+
+bool KexiMainWindowImpl::printPreviewForItem(KexiPart::Item* item,
+ const KexiSimplePrintingSettings& settings, const QString& titleText, bool reload)
+{
+//! @todo: check if changes to this object's design are saved, if not: ask for saving
+//! @todo: accept row changes...
+ KexiSimplePrintingCommand* cmd = d->openedCustomObjectsForItem<KexiSimplePrintingCommand>(
+ item, "KexiSimplePrintingCommand");
+ if (!cmd) {
+ d->addOpenedCustomObjectForItem(
+ item,
+ cmd = new KexiSimplePrintingCommand(this, item->identifier()),
+ "KexiSimplePrintingCommand"
+ );
+ }
+ return cmd->showPrintPreview(settings, titleText, reload);
+}
+
+tristate KexiMainWindowImpl::showPageSetupForItem(KexiPart::Item* item)
+{
+//! @todo: check if changes to this object's design are saved, if not: ask for saving
+//! @todo: accept row changes...
+ return printActionForItem(item, PageSetupForItem);
+}
+
+tristate KexiMainWindowImpl::printActionForItem(KexiPart::Item* item, PrintActionType action)
+{
+ if (!item)
+ return false;
+ KexiPart::Info *info = Kexi::partManager().infoForMimeType( item->mimeType() );
+ if (!info->isPrintingSupported())
+ return false;
+
+ KexiDialogBase *printingDialog = d->pageSetupDialogs[ item->identifier() ];
+ if (printingDialog) {
+ if (!activateWindow(printingDialog))
+ return false;
+ if (action == PreviewItem || action == PrintItem) {
+ QTimer::singleShot(0,printingDialog->selectedView(),
+ (action == PreviewItem) ? SLOT(printPreview()) : SLOT(print()));
+ }
+ return true;
+ }
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ Private::PendingJobType pendingType;
+ KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
+ if (pendingType!=Private::NoJob)
+ return cancelled;
+#else
+ KexiDialogBase *dlg = d->openedDialogFor( item );
+#endif
+
+ if (dlg) {
+ // accept row changes
+ QWidget *prevFocusWidget = focusWidget();
+ dlg->setFocus();
+ d->action_data_save_row->activate();
+ if (prevFocusWidget)
+ prevFocusWidget->setFocus();
+
+ // opened: check if changes made to this dialog are saved, if not: ask for saving
+ if (dlg->neverSaved()) //sanity check
+ return false;
+ if (dlg->dirty()) {
+ KGuiItem saveChanges( KStdGuiItem::save() );
+ saveChanges.setToolTip(i18n("Save changes"));
+ saveChanges.setWhatsThis(
+ i18n( "Pressing this button will save all recent changes made in \"%1\" object." )
+ .arg(item->name()) );
+ KGuiItem doNotSave( KStdGuiItem::no() );
+ doNotSave.setWhatsThis(
+ i18n( "Pressing this button will ignore all unsaved changes made in \"%1\" object." )
+ .arg(dlg->partItem()->name()) );
+
+ QString question;
+ if (action == PrintItem)
+ question = i18n("Do you want to save changes before printing?");
+ else if (action == PreviewItem)
+ question = i18n("Do you want to save changes before making print preview?");
+ else if (action == PageSetupForItem)
+ question = i18n("Do you want to save changes before showing page setup?");
+ else
+ return false;
+
+ const int questionRes = KMessageBox::warningYesNoCancel( this,
+ "<p>"+dlg->part()->i18nMessage("Design of object \"%1\" has been modified.", dlg)
+ .arg(item->name()) + "</p><p>" + question + "</p>",
+ QString::null,
+ saveChanges,
+ doNotSave);
+ if (KMessageBox::Cancel == questionRes)
+ return cancelled;
+ if (KMessageBox::Yes == questionRes) {
+ tristate savingRes = saveObject( dlg, QString::null, true /*dontAsk*/ );
+ if (true != savingRes)
+ return savingRes;
+ }
+ }
+ }
+ KexiPart::Part * printingPart = Kexi::partManager().partForMimeType("kexi/simpleprinting");
+ if (!printingPart)
+ printingPart = new KexiSimplePrintingPart(); //hardcoded as there're no .desktop file
+ KexiPart::Item* printingPartItem = d->prj->createPartItem(
+ printingPart, item->name() //<-- this will look like "table1 : printing" on the window list
+ );
+ QMap<QString,QString> staticObjectArgs;
+ staticObjectArgs["identifier"] = QString::number(item->identifier());
+ if (action == PrintItem)
+ staticObjectArgs["action"] = "print";
+ else if (action == PreviewItem)
+ staticObjectArgs["action"] = "printPreview";
+ else if (action == PageSetupForItem)
+ staticObjectArgs["action"] = "pageSetup";
+ else
+ return false;
+ bool openingCancelled;
+ printingDialog = openObject(printingPartItem, Kexi::DesignViewMode,
+ openingCancelled, &staticObjectArgs);
+ if (openingCancelled)
+ return cancelled;
+ if (!printingDialog) //sanity
+ return false;
+ d->pageSetupDialogs.insert(item->identifier(), printingDialog);
+ d->pageSetupDialogItemID2dataItemID_map.insert(
+ printingDialog->partItem()->identifier(), item->identifier());
+
+ return true;
+}
+
+void KexiMainWindowImpl::slotEditCopySpecialDataTable()
+{
+ KexiPart::Item* item = d->nav->selectedPartItem();
+ if (item)
+ exportItemAsDataTable(item);
+}
+
+tristate KexiMainWindowImpl::copyItemToClipboardAsDataTable(KexiPart::Item* item)
+{
+ if (!item)
+ return false;
+
+ QMap<QString,QString> args;
+ args.insert("destinationType", "clipboard");
+ args.insert("itemId", QString::number(item->identifier()));
+ QDialog *dlg = KexiInternalPart::createModalDialogInstance(
+ "csv_importexport", "KexiCSVExportWizard", this, this, 0, &args);
+ if (!dlg)
+ return false; //error msg has been shown by KexiInternalPart
+ const int result = dlg->exec();
+ delete dlg;
+ return result == QDialog::Rejected ? cancelled : true;
+}
+
+void KexiMainWindowImpl::slotEditPasteSpecialDataTable()
+{
+//! @todo allow data appending (it is not possible now)
+ if (userMode())
+ return;
+ QMap<QString,QString> args;
+ args.insert("sourceType", "clipboard");
+ QDialog *dlg = KexiInternalPart::createModalDialogInstance(
+ "csv_importexport", "KexiCSVImportDialog", this, this, 0, &args);
+ if (!dlg)
+ return; //error msg has been shown by KexiInternalPart
+ dlg->exec();
+ delete dlg;
+}
+
+void KexiMainWindowImpl::slotEditFind()
+{
+// KexiViewBase *view = d->currentViewSupportingAction("edit_findnext");
+ KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface();
+ if (!iface)
+ return;
+ d->updateFindDialogContents(true/*create if does not exist*/);
+ d->findDialog()->setReplaceMode(false);
+
+ d->findDialog()->show();
+ d->findDialog()->setActiveWindow();
+ d->findDialog()->raise();
+}
+
+void KexiMainWindowImpl::slotEditFind(bool next)
+{
+ KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface();
+ if (!iface)
+ return;
+ tristate res = iface->find(
+ d->findDialog()->valueToFind(), d->findDialog()->options(), next);
+ if (~res)
+ return;
+ d->findDialog()->updateMessage( true == res );
+//! @todo result
+}
+
+void KexiMainWindowImpl::slotEditFindNext()
+{
+ slotEditFind( true );
+}
+
+void KexiMainWindowImpl::slotEditFindPrevious()
+{
+ slotEditFind( false );
+}
+
+void KexiMainWindowImpl::slotEditReplace()
+{
+ KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface();
+ if (!iface)
+ return;
+ d->updateFindDialogContents(true/*create if does not exist*/);
+ d->findDialog()->setReplaceMode(true);
+//! @todo slotEditReplace()
+ d->findDialog()->show();
+ d->findDialog()->setActiveWindow();
+}
+
+void KexiMainWindowImpl::slotEditReplaceNext()
+{
+ slotEditReplace( false );
+}
+
+void KexiMainWindowImpl::slotEditReplace(bool all)
+{
+ KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface();
+ if (!iface)
+ return;
+//! @todo add question: "Do you want to replace every occurence of \"%1\" with \"%2\"?
+//! You won't be able to undo this." + "Do not ask again".
+ tristate res = iface->findNextAndReplace(
+ d->findDialog()->valueToFind(), d->findDialog()->valueToReplaceWith(),
+ d->findDialog()->options(), all);
+ d->findDialog()->updateMessage( true == res );
+//! @todo result
+}
+
+void KexiMainWindowImpl::slotEditReplaceAll()
+{
+ slotEditReplace( true );
+}
+
+void KexiMainWindowImpl::addWindow( KMdiChildView* pView, int flags )
+{
+ //maximize this window, if it's
+//!@todo Certain windows' sizes, e.g. forms could have own size configation specified!
+//! Query for this, and if so: give up.
+ if (d->maximizeFirstOpenedChildFrm) {
+ flags |= KMdi::Maximize;
+ d->maximizeFirstOpenedChildFrm = false;
+ }
+ KexiMainWindow::addWindow( pView, flags );
+}
+
+/// TMP (until there's true template support)
+void KexiMainWindowImpl::slotGetNewStuff()
+{
+#ifdef HAVE_KNEWSTUFF
+ if(!d->newStuff)
+ d->newStuff = new KexiNewStuff(this);
+ d->newStuff->download();
+
+ //KNS::DownloadDialog::open(newstuff->customEngine(), "kexi/template");
+#endif
+}
+
+void KexiMainWindowImpl::highlightObject(const QCString& mime, const QCString& name)
+{
+ slotViewNavigator();
+ if (!d->prj)
+ return;
+ KexiPart::Item *item = d->prj->itemForMimeType(mime, name);
+ if (!item)
+ return;
+ if (d->nav) {
+ d->nav->selectItem(*item);
+ }
+}
+
+void KexiMainWindowImpl::slotPartItemSelectedInNavigator(KexiPart::Item* item)
+{
+ Q_UNUSED(item);
+}
+
+#include "keximainwindowimpl.moc"
diff --git a/kexi/main/keximainwindowimpl.h b/kexi/main/keximainwindowimpl.h
new file mode 100644
index 00000000..93545439
--- /dev/null
+++ b/kexi/main/keximainwindowimpl.h
@@ -0,0 +1,538 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXIMAINWINDOWIMPL_H
+#define KEXIMAINWINDOWIMPL_H
+
+#include <kmessagebox.h>
+#include "core/keximainwindow.h"
+#include "core/kexiguimsghandler.h"
+
+class KexiProjectData;
+class KexiActionProxy;
+class KMdiChildView;
+class KexiSimplePrintingSettings;
+
+namespace KexiDB {
+ class Object;
+ class ConnectionData;
+}
+namespace KexiPart {
+ class Info;
+ class Part;
+}
+
+/**
+ * @short Kexi's main window implementation
+ */
+class KEXIMAIN_EXPORT KexiMainWindowImpl : public KexiMainWindow, public KexiGUIMessageHandler
+{
+ Q_OBJECT
+
+ public:
+ /*! Creates an empty mainwindow. */
+ KexiMainWindowImpl();
+ virtual ~KexiMainWindowImpl();
+
+ /*! Used by the main kexi routine. Creates a new Kexi main window and a new KApplication object.
+ kdemain() has to destroy the latter on exit.
+ \return result 1 on error and 0 on success (the result can be used as a result of kdemain()) */
+ static int create(int argc, char *argv[], KAboutData* aboutdata = 0);
+
+ //! \return KexiMainWindowImpl singleton (if it is instantiated)
+ static KexiMainWindowImpl* self() { return dynamic_cast<KexiMainWindowImpl*>(qApp->mainWidget()); }
+
+ //! Project data of currently opened project or NULL if no project here yet.
+ virtual KexiProject *project();
+
+ /*! Registers dialog \a dlg for watching and adds it to the main window's stack. */
+ virtual void registerChild(KexiDialogBase *dlg);
+
+ /*! Activates a window by it's document identifier.
+ \return false if doc couldn't be raised or isn't opened. */
+ bool activateWindow(int id);
+
+ /*! Like above, using \a dlg passed explicitly. Above method just calls this one. */
+ bool activateWindow(KexiDialogBase *dlg);
+
+ /*! Performs startup actions. \return false if application should exit immediately
+ with an error status. */
+ tristate startup();
+
+ /*! \return true if the application window is in the User Mode. */
+ virtual bool userMode() const;
+
+ /*! \return true if opening of item \a item in \a viewMode mode is allowed.
+ userMode() is taken into account as well
+ as KexiPart::Part::supportedUserViewModes() for \a item. */
+ bool openingAllowed(KexiPart::Item* item, int viewMode);
+
+ virtual bool eventFilter( QObject *obj, QEvent * e );
+
+ //! \return popup menu for \a popupName name.
+ virtual QPopupMenu* findPopupMenu(const char *popupName);
+
+ /*! Implemented for KexiMainWindow. */
+ virtual KActionPtrList allActions() const;
+
+ /*! \return currently active dialog (window) od 0 if there is no active dialog.
+ Implemented for KexiMainWindow. */
+ virtual KexiDialogBase* currentDialog() const;
+
+//! @todo move to kexiproject
+ /*! Generates ID for private "document" like Relations window.
+ Private IDs are negative numbers (while ID regular part instance's IDs are >0)
+ Private means that the object is not stored as-is in the project but is somewhat
+ generated and in most cases there is at most one unique instance document of such type (part).
+ To generate this ID, just app-wide internal counter is used. */
+ virtual int generatePrivateID();
+
+ /*! Reimplemented */
+ virtual void readProperties(KConfig *config);
+ virtual void saveProperties(KConfig *config);
+ virtual void saveGlobalProperties( KConfig* sessionConfig );
+
+ public slots:
+ /*! Inherited from KMdiMainFrm: we need to do some tasks before child is closed.
+ Just calls closeDialog(). Use closeDialog() if you need, not this one. */
+ virtual void closeWindow(KMdiChildView *pWnd, bool layoutTaskBar = true);
+
+ /*! Reimplemented for internal reasons. */
+ virtual void addWindow( KMdiChildView* pView, int flags = KMdi::StandardAdd );
+
+ /*! Implemented for KexiMainWindow */
+ virtual tristate closeDialog(KexiDialogBase *dlg);
+
+ /*! Internal implementation. If \a doNotSaveChanges is true,
+ messages asking for saving the will be skipped and the changes will be dropped.
+ This should not be usually used, maybe except for test suites
+ (see kexi/tests/altertable/ directory). */
+ tristate closeDialog(KexiDialogBase *dlg, bool layoutTaskBar, bool doNotSaveChanges = false);
+
+ virtual void detachWindow(KMdiChildView *pWnd,bool bShow=true);
+ virtual void attachWindow(KMdiChildView *pWnd,bool bShow=true,bool bAutomaticResize=false);
+
+//! @todo move part of this to KexiProject, because currently KexiProject::openObject() allows multiple opens!
+ /*! Opens object pointed by \a item in a view \a viewMode.
+ \a staticObjectArgs can be passed for static object
+ (only works when part for this item is of type KexiPart::StaticPart).
+ \a openingCancelled is set to true is opening has been cancelled.
+ \a errorMessage, if not 0, points to a string that can be set to error message
+ if one encountered. */
+ virtual KexiDialogBase* openObject(KexiPart::Item *item, int viewMode,
+ bool &openingCancelled, QMap<QString,QString>* staticObjectArgs = 0,
+ QString* errorMessage = 0);
+
+ //! For convenience
+ virtual KexiDialogBase* openObject(const QCString& mime, const QString& name,
+ int viewMode, bool &openingCancelled, QMap<QString,QString>* staticObjectArgs = 0);
+
+ /*! Closes the object for \a item.
+ \return true on success (closing can be dealyed though), false on failure and cancelled
+ if the object has "opening" job assigned. */
+ virtual tristate closeObject(KexiPart::Item* item);
+
+ /*! Implemented for KexiMainWindow */
+ virtual tristate saveObject( KexiDialogBase *dlg,
+ const QString& messageWhenAskingForName = QString::null, bool dontAsk = false );
+
+ /*! Implemented for KexiMainWindow */
+ virtual tristate getNewObjectInfo( KexiPart::Item *partItem, KexiPart::Part *part,
+ bool& allowOverwriting, const QString& messageWhenAskingForName = QString::null );
+
+ /*! Implemented for KexiMainWindow */
+ virtual void highlightObject(const QCString& mime, const QCString& name);
+
+ /*! Opens project pointed by \a projectData.
+ Application state (e.g. actions) is updated.
+ \a projectData is copied into a project structures.
+ \return true on success */
+ tristate openProject(const KexiProjectData& projectData);
+
+ /*! Helper. Opens project pointed by \a aFileName.
+ If \a aFileName is empty, a connection shortcut (.kexic file name) is obtained from
+ global connection set using \a cdata (if present).
+ In this case:
+ * If connection shortcut has been found and \a dbName (a server database name) is provided
+ 'kexi --skip-dialog --connection file.kexic dbName' is executed (or the project
+ is opened directly if there's no project opened in the current Kexi main window.
+ * If connection shortcut has been found and \a dbName is not provided,
+ 'kexi --skip-dialog file.kexic' is executed (or the connection is opened
+ directly if there's no porject opened in the current Kexi main window. */
+ tristate openProject(const QString& aFileName, KexiDB::ConnectionData *cdata,
+ const QString& dbName = QString::null,
+ const QValueList<KexiProjectData::ObjectInfo>& autoopenObjects = QValueList<KexiProjectData::ObjectInfo>());
+
+ /*! Helper. Opens project pointed by \a aFileName.
+ Like above but \a fileNameForConnectionData can be passed instead of
+ a pointer to connection data itself.
+ \return false if \a fileNameForConnectionData is not empty but there is no such
+ connection in Kexi::connset() for this filename.
+ \a fileNameForConnectionData can be empty. */
+ tristate openProject(const QString& aFileName,
+ const QString& fileNameForConnectionData, const QString& dbName = QString::null);
+
+ /*! Creates a new project usign template pointed by \a projectData.
+ Application state (e.g. actions) is updated.
+ New project data is copied into a project structures.
+ \return true on success */
+ tristate createProjectFromTemplate(const KexiProjectData& projectData);
+
+ /*! Closes current project, \return true on success.
+ Application state (e.g. actions) is updated.
+ \return true on success.
+ If closing was cancelled by user, cancelled is returned. */
+ tristate closeProject();
+
+ //! Shows "print" dialog for \a item.
+ //! \return true on success.
+ virtual tristate printItem(KexiPart::Item* item);
+
+ //! Shows "print preview" dialog.
+ //! \return true on success.
+ virtual tristate printPreviewForItem(KexiPart::Item* item);
+
+ //! Shows "page setup" dialog for \a item.
+ //! \return true on success and cancelled when the action was cancelled.
+ virtual tristate showPageSetupForItem(KexiPart::Item* item);
+
+ /*! Executes custom action for the main window, usually provided by a plugin.
+ Also used by KexiFormEventAction. */
+ virtual tristate executeCustomActionForObject(KexiPart::Item* item, const QString& actionName);
+
+ signals:
+ //! Emitted after opening a project, even after slotAutoOpenObjectsLater().
+ void projectOpened();
+
+ protected:
+ /*! Initialises the User Mode: constructs window according to kexi__final database
+ and loads the specified part.
+ \return true on success or false if e.g. kexi__final does not exist
+ or a fatal exception happened */
+ bool initUserMode(KexiProjectData *projectData);
+
+ /*!
+ Creates navigator (if it's not yet created),
+ lookups items for current project and fills the nav. with not-opened items
+ */
+ void initNavigator();
+
+ void initContextHelp();
+
+ void initPropertyEditor();
+
+ //! reimplementation of events
+// virtual void closeEvent(QCloseEvent *);
+
+ /*! Creates standard actions like new, open, save ... */
+ void initActions();
+
+ /*! Creates user project-wide actions */
+ void initUserActions();
+
+ /*! Sets up the window from user settings (e.g. mdi mode). */
+ void restoreSettings();
+
+ /*! Writes user settings back. */
+ void storeSettings();
+
+ /*! Invalidates availability of all actions for current application state. */
+ void invalidateActions();
+
+ /*! Invalidates action availability for current application state.
+ These actions are dependent on curently selected dialog. */
+ virtual void invalidateSharedActions(QObject *o);
+
+ /*! Invalidates action availability for current application state.
+ These actions only depend on project availability, not on curently selected dialog. */
+ void invalidateProjectWideActions();
+
+ /*! Invalidates action availability for current application state.
+ These actions only depend on curently selected dialog and currently selected view
+ (KexiViewBase derived object) within this dialog. */
+ void invalidateViewModeActions();
+
+ /*! Shows dialog for creating new blank project,
+ and creates one. Dialog is not shown if option for automatic creation
+ is checked or Kexi::startupHandler().projectData() was provided from command line.
+ \a cancelled is set to true if creation has been cancelled (e.g. user answered
+ no when asked for database overwriting, etc.
+ \return true if database was created, false on error or when cancel was pressed */
+ tristate createBlankProject();
+
+ /*! Shows dialog for creating new blank project,
+ and return a data describing it. It the dialog was cancelled,
+ \a cancelled will be set to true (false otherwise).
+ \a shortcutFileName, if not 0, will be set to a shortcut filename
+ (in case when server database project was selected). */
+ KexiProjectData* createBlankProjectData(bool &cancelled, bool confirmOverwrites = true,
+ QString *shortcutFileName = 0);
+
+ void setWindowMenu(QPopupMenu *menu);
+
+ /*! \return focused kexi window (KexiDialogBase or KexiDockBase subclass) */
+// QWidget* focusWindow() const;
+
+ /*! Reimplemented from KexiSharedActionHost:
+ accepts only KexiDockBase and KexiDialogBase subclasses. */
+ virtual bool acceptsSharedActions(QObject *w);
+
+ /*! Performs lookup like in KexiSharedActionHost::focusWindow()
+ but starting from \a w instead of a widget returned by QWidget::focusWidget().
+ \return NULL if no widget matches acceptsSharedActions() or if \a w is NULL. */
+ QWidget* findWindow(QWidget *w);
+
+ /*! Updates application's caption - also shows project's name. */
+ void updateAppCaption();
+
+ void restoreWindowConfiguration(KConfig *config);
+ void storeWindowConfiguration(KConfig *config);
+
+ virtual bool queryClose();
+ virtual bool queryExit();
+
+ /*! Helper: switches to view \a mode. */
+ bool switchToViewMode(int viewMode);
+
+ /*! Helper. Removes and/or adds GUI client for current dialog's view;
+ on switching to other dialog (activeWindowChanged())
+ or on switching to other view within the same dialog (switchToViewMode()). */
+ void updateDialogViewGUIClient(KXMLGUIClient *viewClient);
+
+ /*! Helper. Updates setup of property panel's tabs. Used when switching
+ from \a prevDialog dialog to a current dialog. */
+ void updateCustomPropertyPanelTabs(KexiDialogBase *prevDialog, int prevViewMode);
+
+ /*! @overload void updateCustomPropertyPanelTabs(KexiDialogBase *prevDialog, int prevViewMode) */
+ void updateCustomPropertyPanelTabs(
+ KexiPart::Part *prevDialogPart, int prevViewMode, KexiPart::Part *curDialogPart, int curViewMode );
+
+ /*! Used in openProject when running another Kexi process is required. */
+ tristate openProjectInExternalKexiInstance(const QString& aFileName,
+ KexiDB::ConnectionData *cdata, const QString& dbName);
+
+ /*! Used in openProject when running another Kexi process is required. */
+ tristate openProjectInExternalKexiInstance(const QString& aFileName,
+ const QString& fileNameForConnectionData, const QString& dbName);
+
+ protected slots:
+
+ /*! Called once after timeout (after ctors are executed). */
+ void slotAutoOpenObjectsLater();
+
+ /*! This slot is called if a window changes */
+ void activeWindowChanged(KMdiChildView *dlg);
+
+ /*! Tthis slot is called if a window gets colsed and will unregister stuff */
+ void childClosed(KMdiChildView *dlg);
+
+ void slotPartLoaded(KexiPart::Part* p);
+
+ void slotCaptionForCurrentMDIChild(bool childrenMaximized);
+ void slotNoMaximizedChildFrmLeft(KMdiChildFrm*);
+ void slotLastChildViewClosed();
+ void slotChildViewIsDetachedNow(QWidget*);
+
+ //! internal - creates and initializes kexi project
+ void createKexiProject(KexiProjectData* new_data);
+
+ /*! Handles event when user double clicked (or single -depending on settings)
+ or pressed Return key on the part item in the navigator.
+ This differs from openObject() signal in that if the object is already opened
+ in view mode other than \a viewMode, the mode is not changed.
+ \sa KexiBrowser::openOrActivateItem() */
+ KexiDialogBase* openObjectFromNavigator(KexiPart::Item* item, int viewMode,
+ bool &openingCancelled);
+
+ //! For convenience
+ KexiDialogBase* openObjectFromNavigator(KexiPart::Item* item, int viewMode);
+
+ /*! Creates new object of type defined by \a info part info.
+ \a openingCancelled is set to true is opening has been cancelled.
+ \return true on success. */
+ virtual bool newObject( KexiPart::Info *info, bool& openingCancelled );
+
+ //! For convenience
+ bool newObject( KexiPart::Info *info ) {
+ bool openingCancelled;
+ return newObject(info, openingCancelled);
+ }
+
+ //! For convenience
+ KexiDialogBase* openObject(KexiPart::Item *item, int viewMode,
+ QMap<QString,QString>* staticObjectArgs = 0)
+ {
+ bool openingCancelled;
+ return openObject(item, viewMode, openingCancelled, staticObjectArgs);
+ }
+
+ /*! Removes object pointed by \a item from current project.
+ Asks for confirmation. \return true on success
+ or cancelled if removing was cancelled (only possible if \a dontAsk is false). */
+ tristate removeObject( KexiPart::Item *item, bool dontAsk = false );
+
+ /*! Renames object pointed by \a item to a new name \a _newName.
+ Sets \a success to false on failure. Used as a slot connected
+ to KexiBrowser::renameItem() signal. */
+ void renameObject( KexiPart::Item *item, const QString& _newName, bool &succes );
+
+ /*! Reaction for object rename (signalled by KexiProject).
+ If this item has opened dialog, it's caption is updated,
+ and also optionally application's caption. */
+ virtual void slotObjectRenamed(const KexiPart::Item &item, const QCString& oldName);
+
+ virtual void fillWindowMenu();
+
+ void invalidateSharedActions();
+ void invalidateSharedActionsLater();
+
+ //! Updates the statusbar, navigator and "Insert->....." actions, dependent on read-only state.
+ //! Only called on project opening and closing.
+ void updateReadOnlyState();
+
+ void slotProjectNew();
+ void slotProjectOpen();
+ void slotProjectOpenRecentAboutToShow();
+ void slotProjectOpenRecent(int id);
+ void slotProjectOpenRecentMore();
+ void slotProjectSave();
+ void slotProjectSaveAs();
+ void slotProjectPrint();
+ void slotProjectPrintPreview();
+ void slotProjectPageSetup();
+ void slotProjectProperties();
+ void slotProjectClose();
+ void slotProjectRelations();
+ void slotProjectImportDataTable();
+ void slotProjectExportDataTable();
+ void slotProjectQuit();
+ void slotEditPasteSpecialDataTable();
+ void slotEditCopySpecialDataTable();
+ void slotEditFind();
+ void slotEditFind(bool next); //!< helper
+ void slotEditFindNext();
+ void slotEditFindPrevious();
+ void slotEditReplace(bool all); //!< helper
+ void slotEditReplace();
+ void slotEditReplaceNext();
+ void slotEditReplaceAll();
+ void slotViewNavigator();
+ void slotViewMainArea();
+ void slotViewPropertyEditor();
+ void slotViewDataMode();
+ void slotViewDesignMode();
+ void slotViewTextMode(); //!< sometimes called "SQL View"
+ void slotShowSettings();
+ void slotConfigureKeys();
+ void slotConfigureToolbars();
+ void slotToolsProjectMigration();
+ void slotToolsCompactDatabase();
+
+ /// TMP: Display a dialog to download db examples from internet
+ void slotGetNewStuff();
+
+ void slotTipOfTheDay();
+
+ //! Shows 'important info' dialog, is \a onStartup is false, it's always shown
+ void importantInfo(bool onStartup);
+ void slotImportantInfo(); //!< just importantInfo(false);
+ void slotStartFeedbackAgent();
+
+ void slotOptionsEnableForms(bool show, bool noMessage = false); //temp.
+
+ void slotImportFile();
+ void slotImportServer();
+
+ //! There are performed all actions that need to be done immediately after ctro (using timer)
+ void slotLastActions();
+
+ virtual void acceptPropertySetEditing();
+
+ virtual void propertySetSwitched(KexiDialogBase *dlg, bool force=false,
+ bool preservePrevSelection = true, const QCString& propertyToSelect = QCString());
+
+ /*! Handles changes in 'dirty' flag for dialogs. */
+ void slotDirtyFlagChanged(KexiDialogBase*);
+
+ void slotMdiModeHasBeenChangedTo(KMdi::MdiMode);
+
+ //! reimplemented to add "restart is required" message box
+ virtual void switchToIDEAlMode();
+ void switchToIDEAlMode(bool showMessage);
+ virtual void switchToChildframeMode();
+ void switchToChildframeMode(bool showMessage);
+
+ /*! Shows Project Migration Wizard. \return true on successful migration,
+ cancelled on cancellation, and false on failure.
+ If \a mimeType and \a databaseName are not empty, the wizard will only ask about
+ parameters of destination project and skip pages related to source project.
+ \a cdata connection data can be also provided to preselect server-based connections. */
+ tristate showProjectMigrationWizard(const QString& mimeType, const QString& databaseName,
+ const KexiDB::ConnectionData *cdata = 0);
+
+ //! Receives "selectionChanged()" signal from navigator to update some actions.
+ void slotPartItemSelectedInNavigator(KexiPart::Item* item);
+
+ /*! Receives the "executeItem" signal from navigator to perform "execute" action
+ on \a item. \return true on success */
+ tristate executeItem(KexiPart::Item* item);
+
+ //! Shows "exports as data table" dialog for \a item.
+ tristate exportItemAsDataTable(KexiPart::Item* item);
+
+ //! Shows "copy special as data table" dialog for \a item.
+ tristate copyItemToClipboardAsDataTable(KexiPart::Item* item);
+
+ //! Shows "print" dialog for \a item.
+ //! \return true on success.
+ bool printItem(KexiPart::Item* item, const QString& titleText);
+
+ //! Shows "print" dialog for \a item and \a settings.
+ //! \return true on success.
+ bool printItem(KexiPart::Item* item, const KexiSimplePrintingSettings& settings,
+ const QString& titleText = QString::null);
+
+ /*! Shows "print preview" dialog for \a item.
+ The preview dialog is cached, so \a reload == true is sometimes needed
+ if data or print settings have changed in the meantime.
+ \return true on success. */
+ bool printPreviewForItem(KexiPart::Item* item, const QString& titleText,
+ bool reload);
+
+ //! Shows "print preview" dialog.
+ //! \return true on success.
+ bool printPreviewForItem(KexiPart::Item* item, const KexiSimplePrintingSettings& settings,
+ const QString& titleText = QString::null, bool reload = false);
+
+ /*! Implemented for KexiMainWindow. Helper for printItem() and printPreviewForItem().
+ Also used by KexiFormEventAction.
+ \return true on success and cancelled when the action was cancelled. */
+ tristate printActionForItem(KexiPart::Item* item, PrintActionType action);
+
+ private:
+ class MessageHandler;
+ class Private;
+ Private *d;
+
+ friend class KexiDialogBase;
+};
+
+#endif
+
diff --git a/kexi/main/keximainwindowimpl_p.h b/kexi/main/keximainwindowimpl_p.h
new file mode 100644
index 00000000..b48c7ca0
--- /dev/null
+++ b/kexi/main/keximainwindowimpl_p.h
@@ -0,0 +1,599 @@
+/* This file is part of the KDE projec
+ Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifdef KEXI_NO_PROCESS_EVENTS
+# define KEXI_NO_PENDING_DIALOGS
+#endif
+
+//! @internal safer dictionary
+typedef QMap< int, QGuardedPtr<KexiDialogBase> > KexiDialogDict;
+
+//! @internal
+class KexiMainWindowImpl::Private
+{
+public:
+ Private(KexiMainWindowImpl* w)
+// : dialogs(401)
+ : wnd(w)
+ , m_openedCustomObjectsForItem(1019, true)
+ {
+ propEditor=0;
+ propEditorToolWindow=0;
+ propEditorTabWidget=0;
+ userMode = false;
+ nav=0;
+ navToolWindow=0;
+ prj = 0;
+ curDialogGUIClient=0;
+ curDialogViewGUIClient=0;
+ closedDialogGUIClient=0;
+ closedDialogViewGUIClient=0;
+ nameDialog=0;
+ curDialog=0;
+ m_findDialog=0;
+ block_KMdiMainFrm_eventFilter=false;
+ focus_before_popup=0;
+// relationPart=0;
+ privateIDCounter=0;
+ action_view_nav=0;
+ action_view_propeditor=0;
+ action_view_mainarea=0;
+ action_open_recent_projects_title_id = -1;
+ action_open_recent_connections_title_id = -1;
+ forceDialogClosing=false;
+ insideCloseDialog=false;
+#ifndef KEXI_NO_PENDING_DIALOGS
+ actionToExecuteWhenPendingJobsAreFinished = NoAction;
+#endif
+// callSlotLastChildViewClosedAfterCloseDialog=false;
+ createMenu=0;
+ showImportantInfoOnStartup=true;
+// disableErrorMessages=false;
+// last_checked_mode=0;
+ propEditorDockSeparatorPos=-1;
+ navDockSeparatorPos=-1;
+// navDockSeparatorPosWithAutoOpen=-1;
+ wasAutoOpen = false;
+ dialogExistedBeforeCloseProject = false;
+#ifndef KEXI_SHOW_UNIMPLEMENTED
+ dummy_action = new KActionMenu("", wnd);
+#endif
+ maximizeFirstOpenedChildFrm = false;
+#ifdef HAVE_KNEWSTUFF
+ newStuff = 0;
+#endif
+ mdiModeToSwitchAfterRestart = (KMdi::MdiMode)0;
+ forceShowProjectNavigatorOnCreation = false;
+ forceHideProjectNavigatorOnCreation = false;
+ navWasVisibleBeforeProjectClosing = false;
+ saveSettingsForShowProjectNavigator = true;
+ m_openedCustomObjectsForItem.setAutoDelete(true);
+ }
+ ~Private() {
+ }
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ //! Job type. Currently used for marking items as being opened or closed.
+ enum PendingJobType {
+ NoJob = 0,
+ DialogOpeningJob,
+ DialogClosingJob
+ };
+
+ KexiDialogBase *openedDialogFor( const KexiPart::Item* item, PendingJobType &pendingType )
+ {
+ return openedDialogFor( item->identifier(), pendingType );
+ }
+
+ KexiDialogBase *openedDialogFor( int identifier, PendingJobType &pendingType )
+ {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ QMap<int, PendingJobType>::ConstIterator it = pendingDialogs.find( identifier );
+ if (it==pendingDialogs.constEnd())
+ pendingType = NoJob;
+ else
+ pendingType = it.data();
+
+ if (pendingType == DialogOpeningJob) {
+ return 0;
+ }
+ return (KexiDialogBase*)dialogs[ identifier ];
+ }
+#else
+ KexiDialogBase *openedDialogFor( const KexiPart::Item* item )
+ {
+ return openedDialogFor( item->identifier() );
+ }
+
+ KexiDialogBase *openedDialogFor( int identifier )
+ {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ return (KexiDialogBase*)dialogs[ identifier ];
+ }
+#endif
+
+ void insertDialog(KexiDialogBase *dlg) {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ dialogs.insert(dlg->id(), QGuardedPtr<KexiDialogBase>(dlg));
+#ifndef KEXI_NO_PENDING_DIALOGS
+ pendingDialogs.remove(dlg->id());
+#endif
+ }
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ void addItemToPendingDialogs(const KexiPart::Item* item, PendingJobType jobType) {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ pendingDialogs.replace( item->identifier(), jobType );
+ }
+
+ bool pendingDialogsExist() {
+ if (pendingDialogs.constBegin()!=pendingDialogs.constEnd())
+ kdDebug() << pendingDialogs.constBegin().key() << " " << (int)pendingDialogs.constBegin().data() << endl;
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ return !pendingDialogs.isEmpty();
+ }
+#endif
+
+ void updateDialogId(KexiDialogBase *dlg, int oldItemID) {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ dialogs.remove(oldItemID);
+#ifndef KEXI_NO_PENDING_DIALOGS
+ pendingDialogs.remove(oldItemID);
+#endif
+ dialogs.insert(dlg->id(), QGuardedPtr<KexiDialogBase>(dlg));
+ }
+
+ void removeDialog(int identifier) {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ dialogs.remove(identifier);
+ }
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ void removePendingDialog(int identifier) {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ pendingDialogs.remove(identifier);
+ }
+#endif
+
+ uint openedDialogsCount() {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ return dialogs.count();
+ }
+
+ //! Used in KexiMainWindowImple::closeProject()
+ void clearDialogs() {
+//todo(threads) QMutexLocker dialogsLocker( &dialogsMutex );
+ dialogs.clear();
+#ifndef KEXI_NO_PENDING_DIALOGS
+ pendingDialogs.clear();
+#endif
+ }
+
+ /*! Toggles last checked view mode radio action, if available. */
+ void toggleLastCheckedMode()
+ {
+ if (curDialog.isNull())
+ return;
+ KRadioAction *ra = actions_for_view_modes[ curDialog->currentViewMode() ];
+ if (ra)
+ ra->setChecked(true);
+// if (!last_checked_mode)
+// return;
+// last_checked_mode->setChecked(true);
+ }
+
+/*
+void updatePropEditorDockWidthInfo() {
+ if (propEditor) {
+ KDockWidget *dw = (KDockWidget *)propEditor->parentWidget();
+#if defined(KDOCKWIDGET_P)
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ if (ds) {
+ propEditorDockSeparatorPos = ds->separatorPosInPercent();*/
+/* if (propEditorDockSeparatorPos<=0) {
+ config->setGroup("MainWindow");
+ propEditorDockSeparatorPos = config->readNumEntry("RightDockPosition", 80);
+ ds->setSeparatorPos(propEditorDockSeparatorPos, true);
+ }*/
+ /*}
+#endif
+ }
+ }*/
+
+ void showStartProcessMsg(const QStringList& args)
+ {
+ wnd->showErrorMessage(i18n("Could not start %1 application.").arg(KEXI_APP_NAME),
+ i18n("Command \"%1\" failed.").arg(args.join(" ")));
+ }
+
+ void hideMenuItem(const QString& menuName, const QString& itemText, bool alsoSeparator)
+ {
+ QPopupMenu *pm = popups[menuName.ascii()];
+ if (!pm)
+ return;
+ uint i=0;
+ const uint c = pm->count();
+ for (;i<c;i++) {
+ kdDebug() << pm->text( pm->idAt(i) ) <<endl;
+ if (pm->text( pm->idAt(i) ).lower().stripWhiteSpace()==itemText.lower().stripWhiteSpace())
+ break;
+ }
+ if (i<c) {
+ pm->setItemVisible( pm->idAt(i), false );
+ if (alsoSeparator)
+ pm->setItemVisible( pm->idAt(i+1), false ); //also separator
+ }
+ }
+
+ void disableMenuItem(const QString& menuName, const QString& itemText)
+ {
+ QPopupMenu *pm = popups[menuName.ascii()];
+ if (!pm)
+ return;
+ uint i=0;
+ const uint c = pm->count();
+ for (;i<c;i++) {
+ if (pm->text( pm->idAt(i) ).lower().stripWhiteSpace()==itemText.lower().stripWhiteSpace())
+ break;
+ }
+ if (i<c)
+ pm->setItemEnabled( pm->idAt(i), false );
+ }
+
+ void updatePropEditorVisibility(int viewMode)
+ {
+ if (propEditorToolWindow) {
+ if (viewMode==0 || viewMode==Kexi::DataViewMode) {
+#ifdef PROPEDITOR_VISIBILITY_CHANGES
+ wnd->makeDockInvisible( wnd->manager()->findWidgetParentDock(propEditor) );
+// propEditorToolWindow->hide();
+#endif
+ } else {
+ //propEditorToolWindow->show();
+ QWidget *origFocusWidget = qApp->focusWidget();
+ wnd->makeWidgetDockVisible(propEditorTabWidget);
+ if (origFocusWidget)
+ origFocusWidget->setFocus();
+/*moved
+#if defined(KDOCKWIDGET_P)
+ KDockWidget *dw = (KDockWidget *)propEditor->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+ ds->setSeparatorPosInPercent(config->readNumEntry("RightDockPosition", 80));//%
+#endif*/
+ }
+ }
+ }
+
+ void restoreNavigatorWidth()
+ {
+#if defined(KDOCKWIDGET_P)
+ if (wnd->mdiMode()==KMdi::ChildframeMode || wnd->mdiMode()==KMdi::TabPageMode) {
+ KDockWidget *dw = (KDockWidget *)nav->parentWidget();
+ KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
+// ds->setKeepSize(true);
+
+ config->setGroup("MainWindow");
+# if KDE_VERSION >= KDE_MAKE_VERSION(3,4,0)
+
+ if (wasAutoOpen) //(dw2->isVisible())
+// ds->setSeparatorPosInPercent( 100 * nav->width() / wnd->width() );
+ ds->setSeparatorPosInPercent(
+ QMAX(QMAX( config->readNumEntry("LeftDockPositionWithAutoOpen",20),
+ config->readNumEntry("LeftDockPosition",20)),20)
+ );
+ else
+ ds->setSeparatorPosInPercent(
+ QMAX(20, config->readNumEntry("LeftDockPosition", 20/* % */)));
+
+ // dw->resize( d->config->readNumEntry("LeftDockPosition", 115/* % */), dw->height() );
+# else
+ //there were problems on KDE < 3.4
+ ds->setSeparatorPosInPercent( 20 );
+# endif
+ //if (!wasAutoOpen) //(dw2->isVisible())
+// ds->setSeparatorPos( ds->separatorPos(), true );
+ }
+#endif
+ }
+
+ template<class type>
+ type *openedCustomObjectsForItem(KexiPart::Item* item, const char* name)
+ {
+ if (!item || !name) {
+ kdWarning() <<
+ "KexiMainWindowImpl::Private::openedCustomObjectsForItem(): !item || !name" << endl;
+ return 0;
+ }
+ QString key( QString::number(item->identifier()) + name );
+ return dynamic_cast<type*>( m_openedCustomObjectsForItem.find( key.latin1() ) );
+ }
+
+ void addOpenedCustomObjectForItem(KexiPart::Item* item, QObject* object, const char* name)
+ {
+ QString key = QString::number(item->identifier()) + name;
+ m_openedCustomObjectsForItem.insert( key.latin1(), object );
+ }
+
+ KexiFindDialog *findDialog() {
+ if (!m_findDialog) {
+ m_findDialog = new KexiFindDialog(wnd);
+ m_findDialog->setActions( action_edit_findnext, action_edit_findprev,
+ action_edit_replace, action_edit_replace_all );
+/* connect(m_findDialog, SIGNAL(findNext()), action_edit_findnext, SLOT(activate()));
+ connect(m_findDialog, SIGNAL(find()), wnd, SLOT(slotEditFindNext()));
+ connect(m_findDialog, SIGNAL(replace()), wnd, SLOT(slotEditReplaceNext()));
+ connect(m_findDialog, SIGNAL(replaceAll()), wnd, SLOT(slotEditReplaceAll()));*/
+ }
+ return m_findDialog;
+ }
+
+ /*! Updates the find/replace dialog depending on the active view.
+ Nothing is performed if the dialog is not instantiated yet or is invisible. */
+ void updateFindDialogContents(bool createIfDoesNotExist = false) {
+ if (!createIfDoesNotExist && (!m_findDialog || !m_findDialog->isVisible()))
+ return;
+ KexiSearchAndReplaceViewInterface* iface = currentViewSupportingSearchAndReplaceInterface();
+ if (!iface) {
+ if (m_findDialog) {
+ m_findDialog->setButtonsEnabled(false);
+ m_findDialog->setLookInColumnList(QStringList(), QStringList());
+ }
+ return;
+ }
+//! @todo use ->caption() here, depending on global settings related to displaying captions
+ findDialog()->setObjectNameForCaption(curDialog->partItem()->name());
+
+ QStringList columnNames;
+ QStringList columnCaptions;
+ QString currentColumnName; // for 'look in'
+ if (!iface->setupFindAndReplace(columnNames, columnCaptions, currentColumnName)) {
+ m_findDialog->setButtonsEnabled(false);
+ m_findDialog->setLookInColumnList(QStringList(), QStringList());
+ return;
+ }
+ m_findDialog->setButtonsEnabled(true);
+
+ /* //update "look in" list
+ KexiTableViewColumn::List columns( dataAwareObject()->data()->columns );
+ QStringList columnNames;
+ QStringList columnCaptions;
+ for (KexiTableViewColumn::ListIterator it(columns); it.current(); ++it) {
+ if (!it.current()->visible())
+ continue;
+ columnNames.append( it.current()->field()->name() );
+ columnCaptions.append( it.current()->captionAliasOrName() );
+ }*/
+ const QString prevColumnName( m_findDialog->currentLookInColumnName());
+ m_findDialog->setLookInColumnList(columnNames, columnCaptions);
+ m_findDialog->setCurrentLookInColumnName( prevColumnName );
+ }
+
+ //! \return the current view if it supports \a actionName, otherwise returns 0.
+ KexiViewBase *currentViewSupportingAction(const char* actionName) const
+ {
+ if (!curDialog)
+ return 0;
+ KexiViewBase *view = curDialog->selectedView();
+ if (!view)
+ return 0;
+ KAction *action = view->sharedAction(actionName);
+ if (!action || !action->isEnabled())
+ return 0;
+ return view;
+ }
+
+ //! \return the current view if it supports KexiSearchAndReplaceViewInterface.
+ KexiSearchAndReplaceViewInterface* currentViewSupportingSearchAndReplaceInterface() const
+ {
+ if (!curDialog)
+ return 0;
+ KexiViewBase *view = curDialog->selectedView();
+ if (!view)
+ return 0;
+ return dynamic_cast<KexiSearchAndReplaceViewInterface*>(view);
+ }
+
+ KexiMainWindowImpl *wnd;
+ KexiStatusBar *statusBar;
+ KexiProject *prj;
+ KConfig *config;
+#ifndef KEXI_NO_CTXT_HELP
+ KexiContextHelp *ctxHelp;
+#endif
+ KexiBrowser *nav;
+ KTabWidget *propEditorTabWidget;
+ //! poits to kexi part which has been previously used to setup proppanel's tabs using
+ //! KexiPart::setupCustomPropertyPanelTabs(), in updateCustomPropertyPanelTabs().
+ QGuardedPtr<KexiPart::Part> partForPreviouslySetupPropertyPanelTabs;
+ QMap<KexiPart::Part*, int> recentlySelectedPropertyPanelPages;
+ QGuardedPtr<KexiPropertyEditorView> propEditor;
+ QGuardedPtr<KoProperty::Set> propBuffer;
+
+ KXMLGUIClient *curDialogGUIClient, *curDialogViewGUIClient,
+ *closedDialogGUIClient, *closedDialogViewGUIClient;
+ QGuardedPtr<KexiDialogBase> curDialog;
+
+ KexiNameDialog *nameDialog;
+
+ QTimer timer; //helper timer
+// QSignalMapper *actionMapper;
+
+ QAsciiDict<QPopupMenu> popups; //list of menu popups
+ QPopupMenu *createMenu;
+
+ QString origAppCaption; //<! original application's caption (without project name)
+ QString appCaptionPrefix; //<! application's caption prefix - prj name (if opened), else: null
+
+#ifndef KEXI_SHOW_UNIMPLEMENTED
+ KActionMenu *dummy_action;
+#endif
+
+ //! project menu
+ KAction *action_save, *action_save_as, *action_close,
+ *action_project_properties, *action_open_recent_more,
+ *action_project_relations, *action_project_import_data_table,
+ *action_project_export_data_table,
+ *action_project_print, *action_project_print_preview,
+ *action_project_print_setup;
+// KRecentFilesAction *action_open_recent;
+ KActionMenu *action_open_recent, *action_show_other;
+// int action_open_recent_more_id;
+ int action_open_recent_projects_title_id,
+ action_open_recent_connections_title_id;
+
+ //! edit menu
+ KAction *action_edit_delete, *action_edit_delete_row,
+ *action_edit_cut, *action_edit_copy, *action_edit_paste,
+ *action_edit_find, *action_edit_findnext, *action_edit_findprev,
+ *action_edit_replace, *action_edit_replace_all,
+ *action_edit_select_all,
+ *action_edit_undo, *action_edit_redo,
+ *action_edit_insert_empty_row,
+ *action_edit_edititem, *action_edit_clear_table,
+ *action_edit_paste_special_data_table,
+ *action_edit_copy_special_data_table;
+
+ //! view menu
+ KAction *action_view_nav, *action_view_propeditor, *action_view_mainarea;
+ KRadioAction *action_view_data_mode, *action_view_design_mode, *action_view_text_mode;
+ QIntDict<KRadioAction> actions_for_view_modes;
+// KRadioAction *last_checked_mode;
+#ifndef KEXI_NO_CTXT_HELP
+ KToggleAction *action_show_helper;
+#endif
+ //! data menu
+ KAction *action_data_save_row;
+ KAction *action_data_cancel_row_changes;
+ KAction *action_data_execute;
+
+ //! format menu
+ KAction *action_format_font;
+
+ //! tools menu
+ KAction *action_tools_data_migration, *action_tools_compact_database;
+ KActionMenu *action_tools_scripts;
+
+ //! window menu
+ KAction *action_window_next, *action_window_previous;
+
+ //! settings menu
+ KAction *action_configure;
+
+ //! for dock windows
+ KMdiToolViewAccessor* navToolWindow;
+ KMdiToolViewAccessor* propEditorToolWindow;
+
+ QGuardedPtr<QWidget> focus_before_popup;
+// KexiRelationPart *relationPart;
+
+ int privateIDCounter; //!< counter: ID for private "document" like Relations window
+
+ bool block_KMdiMainFrm_eventFilter : 1;
+
+ //! Set to true only in destructor, used by closeDialog() to know if
+ //! user can cancel dialog closing. If true user even doesn't see any messages
+ //! before closing a dialog. This is for extremely sanity... and shouldn't be even needed.
+ bool forceDialogClosing : 1;
+
+ //! Indicates that we're inside closeDialog() method - to avoid inf. recursion
+ //! on dialog removing
+ bool insideCloseDialog : 1;
+
+#ifndef KEXI_NO_PENDING_DIALOGS
+ //! Used in executeActionWhenPendingJobsAreFinished().
+ enum ActionToExecuteWhenPendingJobsAreFinished {
+ NoAction,
+ QuitAction,
+ CloseProjectAction
+ };
+ ActionToExecuteWhenPendingJobsAreFinished actionToExecuteWhenPendingJobsAreFinished;
+
+ void executeActionWhenPendingJobsAreFinished() {
+ ActionToExecuteWhenPendingJobsAreFinished a = actionToExecuteWhenPendingJobsAreFinished;
+ actionToExecuteWhenPendingJobsAreFinished = NoAction;
+ switch (a) {
+ case QuitAction:
+ qApp->quit();
+ break;
+ case CloseProjectAction:
+ wnd->closeProject();
+ break;
+ default:;
+ }
+ }
+#endif
+
+ //! Used for delayed dialogs closing for 'close all'
+ QPtrList<KexiDialogBase> windowsToClose;
+
+ //! Opened page setup dialogs, used by printOrPrintPreviewForItem().
+ QIntDict<KexiDialogBase> pageSetupDialogs;
+
+ /*! A map from Kexi dialog to "print setup" part item's ID of the data item
+ used by closeDialog() to find an ID of the data item, so the entry
+ can be removed from pageSetupDialogs dictionary. */
+ QMap<int, int> pageSetupDialogItemID2dataItemID_map;
+
+ //! Used in several places to show info dialog at startup (only once per session)
+ //! before displaying other stuff
+ bool showImportantInfoOnStartup : 1;
+
+// //! Used sometimes to block showErrorMessage()
+// bool disableErrorMessages : 1;
+
+ //! Indicates if project is started in User Mode
+ bool userMode : 1;
+
+ //! Indicates if project navigator should be visible
+ bool isProjectNavigatorVisible : 1;
+
+ //! Used on opening 1st child window
+ bool maximizeFirstOpenedChildFrm : 1;
+
+ //! Set in restoreSettings() and used in initNavigator()
+ //! to customize navigator visibility on startup
+ bool forceShowProjectNavigatorOnCreation : 1;
+ bool forceHideProjectNavigatorOnCreation : 1;
+
+ bool navWasVisibleBeforeProjectClosing : 1;
+ bool saveSettingsForShowProjectNavigator : 1;
+#ifdef HAVE_KNEWSTUFF
+ KexiNewStuff *newStuff;
+#endif
+
+ //! Used by openedCustomObjectsForItem() and addOpenedCustomObjectForItem()
+ QAsciiDict<QObject> m_openedCustomObjectsForItem;
+
+ int propEditorDockSeparatorPos, navDockSeparatorPos;
+// int navDockSeparatorPosWithAutoOpen;
+ bool wasAutoOpen;
+ bool dialogExistedBeforeCloseProject;
+
+ KMdi::MdiMode mdiModeToSwitchAfterRestart;
+
+ private:
+ //! @todo move to KexiProject
+ KexiDialogDict dialogs;
+#ifndef KEXI_NO_PROCESS_EVENTS
+ QMap<int, PendingJobType> pendingDialogs; //!< part item identifiers for dialogs whoose opening has been started
+ //todo(threads) QMutex dialogsMutex; //!< used for locking dialogs and pendingDialogs dicts
+#endif
+ KexiFindDialog *m_findDialog;
+};
diff --git a/kexi/main/kexinamedialog.cpp b/kexi/main/kexinamedialog.cpp
new file mode 100644
index 00000000..85f7f04a
--- /dev/null
+++ b/kexi/main/kexinamedialog.cpp
@@ -0,0 +1,111 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "kexinamedialog.h"
+
+KexiNameDialog::KexiNameDialog(const QString& message,
+ QWidget * parent, const char * name)
+ : KDialogBase(KDialogBase::Plain, QString::null,
+ KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Help,
+ KDialogBase::Ok,
+ parent, name)
+{
+// QHBox ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 )
+ m_widget= new KexiNameWidget(message, plainPage(), "KexiNameWidget");
+ init();
+}
+
+KexiNameDialog::KexiNameDialog(const QString& message,
+ const QString& nameLabel, const QString& nameText,
+ const QString& captionLabel, const QString& captionText,
+ QWidget * parent, const char * name)
+ : KDialogBase(KDialogBase::Plain, QString::null,
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ parent, name)
+{
+ m_widget= new KexiNameWidget(message, nameLabel, nameText,
+ captionLabel, captionText, plainPage(), "KexiNameWidget");
+ init();
+}
+
+KexiNameDialog::~KexiNameDialog()
+{
+}
+
+void KexiNameDialog::init()
+{
+ QGridLayout *lyr = new QGridLayout(plainPage(), 2, 3);
+ m_icon = new QLabel( plainPage(), "icon" );
+ m_icon->setAlignment( int( AlignTop | AlignLeft ) );
+ m_icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred,1,0));
+ m_icon->setFixedWidth(50);
+ lyr->addWidget(m_icon,0,0);
+
+ m_widget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred,1,0));
+ lyr->addWidget(m_widget,0,1);
+ lyr->addItem(new QSpacerItem( 25, 10, QSizePolicy::Expanding, QSizePolicy::Minimum ), 0, 2);
+ lyr->addItem(new QSpacerItem( 5, 10, QSizePolicy::Minimum, QSizePolicy::Expanding ), 1, 1);
+// m_widget->captionLineEdit()->selectAll();
+// m_widget->captionLineEdit()->setFocus();
+ connect(m_widget,SIGNAL(messageChanged()),this, SLOT(updateSize()));
+ updateSize();
+ enableButtonOK( true );
+ slotTextChanged();
+ connect(m_widget, SIGNAL(textChanged()), this, SLOT(slotTextChanged()));
+}
+
+void KexiNameDialog::updateSize()
+{
+// resize( QSize(400, 140 + (m_widget->lbl_message->isVisible()?m_widget->lbl_message->height():0) )
+ resize( QSize(400, 140 + (!m_widget->lbl_message->text().isEmpty()?m_widget->lbl_message->height():0) )
+ .expandedTo(minimumSizeHint()) );
+// updateGeometry();
+}
+
+void KexiNameDialog::slotTextChanged()
+{
+ bool enable = true;
+ if (m_widget->isNameRequired() && m_widget->nameText().isEmpty()
+ || m_widget->isCaptionRequired() && m_widget->captionText().isEmpty())
+ enable = false;
+ enableButtonOK( enable );
+}
+
+void KexiNameDialog::accept()
+{
+ if (!m_widget->checkValidity())
+ return;
+ KDialogBase::accept();
+}
+
+void KexiNameDialog::setDialogIcon(const QPixmap& icon)
+{
+ m_icon->setPixmap(icon);
+}
+
+void KexiNameDialog::show()
+{
+ m_widget->captionLineEdit()->selectAll();
+ m_widget->captionLineEdit()->setFocus();
+ KDialogBase::show();
+}
+
+#include "kexinamedialog.moc"
+
diff --git a/kexi/main/kexinamedialog.h b/kexi/main/kexinamedialog.h
new file mode 100644
index 00000000..27707c0d
--- /dev/null
+++ b/kexi/main/kexinamedialog.h
@@ -0,0 +1,61 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXINAMEDIALOG_H
+#define KEXINAMEDIALOG_H
+
+#include <kdialogbase.h>
+
+#include "kexinamewidget.h"
+
+class KEXIMAIN_EXPORT KexiNameDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ KexiNameDialog(const QString& message,
+ QWidget * parent = 0, const char * name = 0);
+
+ KexiNameDialog(const QString& message,
+ const QString& nameLabel, const QString& nameText,
+ const QString& captionLabel, const QString& captionText,
+ QWidget * parent = 0, const char * name = 0);
+
+ virtual ~KexiNameDialog();
+
+ KexiNameWidget* widget() const { return m_widget; }
+
+ virtual void show();
+
+ public slots:
+ virtual void setDialogIcon(const QPixmap& icon);
+
+ protected slots:
+ void slotTextChanged();
+ virtual void accept();
+ void updateSize();
+
+ protected:
+ void init();
+
+ QLabel *m_icon;
+ KexiNameWidget* m_widget;
+};
+
+#endif
diff --git a/kexi/main/kexinamewidget.cpp b/kexi/main/kexinamewidget.cpp
new file mode 100644
index 00000000..39cb084a
--- /dev/null
+++ b/kexi/main/kexinamewidget.cpp
@@ -0,0 +1,236 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "kexinamewidget.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+
+#include <kexiutils/validator.h>
+#include <kexiutils/identifier.h>
+#include <core/kexi.h>
+
+using namespace KexiUtils;
+
+KexiNameWidget::KexiNameWidget( const QString& message,
+ QWidget* parent, const char* name, WFlags fl )
+ : QWidget(parent, name, fl)
+{
+ init(message, QString::null, QString::null, QString::null, QString::null);
+}
+
+KexiNameWidget::KexiNameWidget(const QString& message,
+ const QString& nameLabel, const QString& nameText,
+ const QString& captionLabel, const QString& captionText,
+ QWidget * parent, const char * name, WFlags fl)
+{
+ Q_UNUSED( parent );
+ Q_UNUSED( name );
+ Q_UNUSED( fl );
+
+ init(message, nameLabel, nameText, captionLabel, captionText);
+}
+
+void KexiNameWidget::init(
+ const QString& message,
+ const QString& nameLabel, const QString& nameText,
+ const QString& captionLabel, const QString& captionText)
+{
+ Q_UNUSED( captionText );
+
+ m_le_name_txtchanged_disable = false;
+ m_le_name_autofill = true;
+ m_caption_required = false;
+
+ lyr = new QGridLayout( this, 1, 1, 0, 6, "lyr");
+
+ lbl_message = new QLabel( this, "message" );
+ setMessageText( message );
+ lbl_message->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ lbl_message->setAlignment( QLabel::AlignTop | QLabel::WordBreak );
+ lyr->addMultiCellWidget( lbl_message, 0, 0, 0, 1 );
+
+ lbl_caption = new QLabel( captionLabel.isEmpty() ? i18n( "Caption:" ) : captionLabel,
+ this, "lbl_caption" );
+ lyr->addWidget( lbl_caption, 1, 0 );
+
+ lbl_name = new QLabel( nameLabel.isEmpty() ? tr( "Name:" ) : nameLabel,
+ this, "lbl_name" );
+ lyr->addWidget( lbl_name, 2, 0 );
+
+ le_caption = new KLineEdit( nameText, this, "le_caption" );
+ le_caption->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed, 1, 0));
+ lyr->addWidget( le_caption, 1, 1 );
+
+ le_name = new KLineEdit( nameText, this, "le_name" );
+ le_name->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed,1,0));
+ Validator *idValidator = new IdentifierValidator(0, "id_val");
+ le_name->setValidator( m_validator = new MultiValidator(idValidator, this, "val") );
+ lyr->addWidget( le_name, 2, 1 );
+
+ setFocusProxy(le_caption);
+ resize( QSize(342, 123).expandedTo(minimumSizeHint()) );
+
+ m_nameWarning = i18n("Please enter the name.");
+ m_captionWarning = i18n("Please enter the caption.");
+
+ connect(le_caption, SIGNAL(textChanged(const QString&)),
+ this,SLOT(slotCaptionTxtChanged(const QString&)));
+ connect(le_name, SIGNAL(textChanged(const QString&)),
+ this,SLOT(slotNameTxtChanged(const QString&)));
+ connect(le_caption, SIGNAL(returnPressed()),
+ this,SIGNAL(returnPressed()));
+ connect(le_name, SIGNAL(returnPressed()),
+ this,SIGNAL(returnPressed()));
+}
+
+KexiNameWidget::~KexiNameWidget()
+{
+}
+
+void KexiNameWidget::slotCaptionTxtChanged(const QString &capt)
+{
+ emit textChanged();
+ if (le_name->text().isEmpty())
+ m_le_name_autofill=true;
+ if (m_le_name_autofill) {
+ m_le_name_txtchanged_disable = true;
+ le_name->setText( string2Identifier(capt).lower() );
+ m_le_name_txtchanged_disable = false;
+ }
+}
+
+void KexiNameWidget::slotNameTxtChanged(const QString &)
+{
+ emit textChanged();
+ if (m_le_name_txtchanged_disable)
+ return;
+ m_le_name_autofill = false;
+}
+
+void KexiNameWidget::clear()
+{
+ le_name->clear();
+ le_caption->clear();
+}
+
+bool KexiNameWidget::empty() const
+{
+ return le_name->text().isEmpty() || le_caption->text().stripWhiteSpace().isEmpty();
+}
+
+void KexiNameWidget::setNameRequired( bool set )
+{ m_validator->setAcceptsEmptyValue(!set); }
+
+bool KexiNameWidget::isNameRequired() const
+{ return !m_validator->acceptsEmptyValue(); }
+
+void KexiNameWidget::setCaptionText(const QString& capt)
+{
+ le_caption->setText(capt);
+ m_le_name_autofill = true;
+}
+
+void KexiNameWidget::setNameText(const QString& name)
+{
+ le_name->setText(name);
+ m_le_name_autofill = true;
+}
+
+void KexiNameWidget::setMessageText(const QString& msg)
+{
+ if (msg.stripWhiteSpace().isEmpty()) {
+ lbl_message->setText("");
+ lbl_message->hide();
+ } else {
+ lbl_message->setText(msg.stripWhiteSpace()+"<br>");
+ lbl_message->show();
+ }
+ messageChanged();
+}
+
+QString KexiNameWidget::captionText() const
+{
+ return le_caption->text();
+}
+
+QString KexiNameWidget::nameText() const
+{
+ return le_name->text().lower();
+}
+
+bool KexiNameWidget::checkValidity()
+{
+ if (isNameRequired() && le_name->text().stripWhiteSpace().isEmpty()) {
+ KMessageBox::sorry(0, m_nameWarning);
+ le_name->setFocus();
+ return false;
+ }
+ if (isCaptionRequired() && le_caption->text().stripWhiteSpace().isEmpty()) {
+ KMessageBox::sorry(0, m_captionWarning);
+ le_caption->setFocus();
+ return false;
+ }
+ QString dummy, message, details;
+ if (m_validator->check(dummy, le_name->text(), message, details)
+ ==Validator::Error) {
+ KMessageBox::detailedSorry(0, message, details);
+ le_name->setFocus();
+ return false;
+ }
+ return true;
+}
+
+Validator *KexiNameWidget::nameValidator() const
+{
+ return m_validator;
+}
+
+void KexiNameWidget::addNameSubvalidator( Validator* validator, bool owned )
+{
+ m_validator->addSubvalidator( validator, owned );
+}
+
+/*bool KexiNameWidget::eventFilter( QObject *obj, QEvent *ev )
+{
+ if (ev->type()==QEvent::FocusOut && !acceptsEmptyValue()) {
+ if (obj==le_name) {
+ if (le_name->text().isEmpty()) {
+ KMessageBox::information(0, m_nameWarning);
+ le_name->setFocus();
+ return true;
+ }
+ }
+ else if (obj==le_caption) {
+ if (le_caption->text().isEmpty()) {
+ KMessageBox::information(0, m_captionWarning);
+ le_caption->setFocus();
+ return true;
+ }
+ }
+ }
+ return false;
+}*/
+
+#include "kexinamewidget.moc"
+
diff --git a/kexi/main/kexinamewidget.h b/kexi/main/kexinamewidget.h
new file mode 100644
index 00000000..07962b6c
--- /dev/null
+++ b/kexi/main/kexinamewidget.h
@@ -0,0 +1,142 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXINAMEWIDGET_H
+#define KEXINAMEWIDGET_H
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <klineedit.h>
+
+namespace KexiUtils {
+class Validator;
+class MultiValidator;
+}
+
+class KEXIMAIN_EXPORT KexiNameWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ KexiNameWidget(const QString& message,
+ QWidget * parent = 0, const char * name = 0, WFlags fl = 0);
+
+ KexiNameWidget(const QString& message,
+ const QString& nameLabel, const QString& nameText,
+ const QString& captionLabel, const QString& captionText,
+ QWidget * parent = 0, const char * name = 0, WFlags fl = 0);
+
+ virtual ~KexiNameWidget();
+
+ QLabel* captionLabel() const { return lbl_caption; }
+ QLabel* nameLabel() const { return lbl_name; }
+ KLineEdit* captionLineEdit() const { return le_caption; }
+ KLineEdit* nameLineEdit() const { return le_name; }
+
+ QString messageText() const { return lbl_message->text(); }
+
+ void setMessageText(const QString& msg);
+
+ //! \return entered caption text
+ QString captionText() const;
+
+ void setCaptionText(const QString& capt);
+ //! \return entered name text, always in lower case
+
+ QString nameText() const;
+
+ void setNameText(const QString& name);
+
+ /*! Sets i18n'ed warning message displayed when user leaves 'name' field
+ without filling it (if acceptsEmptyValue() is false).
+ By default the message is equal "Please enter the name.". */
+ void setWarningForName( const QString& txt ) { m_nameWarning = txt; }
+
+ /*! Sets i18n'ed warning message displayed when user leaves 'name' field
+ without filling it (if acceptsEmptyValue() is false).
+ By default the message is equal "Please enter the caption." */
+ void setWarningForCaption( const QString& txt ) { m_captionWarning = txt; }
+
+ /*! \return true if name or caption is empty. */
+ bool empty() const;
+
+ KexiUtils::Validator *nameValidator() const;
+
+ /*! Adds subvalidator for name field. In fact it's is added to internal
+ multivalidator. If \a owned is true, \a validator will be owned by the object.
+ \sa MultiValidator::addSubvalidator(). */
+ void addNameSubvalidator( KexiUtils::Validator* validator, bool owned = true );
+
+ /*! \return true if name text cannot be empty (true by default). */
+ bool isNameRequired() const;
+
+ void setNameRequired( bool set );
+
+ /*! \return true if caption text cannot be empty (false by default). */
+ bool isCaptionRequired() const { return m_caption_required; }
+
+ void setCaptionRequired(bool set) { m_caption_required = set; }
+
+ public slots:
+ /*! Clears both name and caption. */
+ virtual void clear();
+
+ /*! Checks if both fields have valid values
+ (i.e. not empty if acceptsEmptyValue() is false).
+ If not, warning message is shown and false is returned. */
+ bool checkValidity();
+
+ signals:
+ /*! Emitted whenever return key is pressed on name or caption label. */
+ void returnPressed();
+
+ /*! Emitted whenever the caption or the name text changes */
+ void textChanged();
+
+ /*! Emitted whenever the message changes */
+ void messageChanged();
+
+ protected slots:
+ void slotNameTxtChanged(const QString&);
+ void slotCaptionTxtChanged(const QString&);
+// bool eventFilter( QObject *obj, QEvent *ev );
+
+ protected:
+ void init(
+ const QString& message,
+ const QString& nameLabel, const QString& nameText,
+ const QString& captionLabel, const QString& captionText);
+
+ QLabel* lbl_message;
+ QLabel* lbl_caption;
+ QLabel* lbl_name;
+ KLineEdit* le_caption;
+ KLineEdit* le_name;
+ QGridLayout* lyr;
+ KexiUtils::MultiValidator *m_validator;
+ QString m_nameWarning, m_captionWarning;
+
+ bool m_le_name_txtchanged_disable : 1;
+ bool m_le_name_autofill : 1;
+ bool m_caption_required : 1;
+
+ friend class KexiNameDialog;
+};
+
+#endif
diff --git a/kexi/main/kexinewstuff.cpp b/kexi/main/kexinewstuff.cpp
new file mode 100644
index 00000000..adc0fc83
--- /dev/null
+++ b/kexi/main/kexinewstuff.cpp
@@ -0,0 +1,81 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_KNEWSTUFF
+
+#include <kdebug.h>
+#include <ktar.h>
+#include <qdir.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kdeversion.h>
+
+#include "kexinewstuff.h"
+
+KexiNewStuff::KexiNewStuff(QWidget *parent)
+ : KNewStuff( "kexi/template"
+#if KDE_IS_VERSION(3,3,0)
+ , "http://download.kde.org/khotnewstuff/kexi-providers.xml"
+#endif
+ , parent)
+{
+ // Prevent GHNS to deny downloading a second time. If GHNS
+ // fails to download something, it still marks the thing as
+ // successfully downloaded and therefore we arn't able to
+ // download it again :-/
+ KGlobal::config()->deleteGroup("KNewStuffStatus");
+}
+
+KexiNewStuff::~KexiNewStuff()
+{
+}
+
+bool
+KexiNewStuff::install(const QString &fileName)
+{
+ kdDebug() << "KexiNewStuff::install(): " << fileName << endl;
+
+ KTar archive( fileName );
+ if ( !archive.open( IO_ReadOnly ) ) {
+ kdDebug() << QString("KexiNewStuff::install: Failed to open archivefile \"%1\"").arg(fileName) << endl;
+ return false;
+ }
+ const KArchiveDirectory *archiveDir = archive.directory();
+ const QString destDir = KFileDialog::getExistingDirectory(
+ ":DownloadExampleDatabases", parentWidget(),
+ i18n("Choose Directory Where to Install Example Database"));
+ if (destDir.isEmpty()) {
+ kdDebug() << QString("KexiNewStuff::install: Destination-directory is empty.") << endl;
+ return false;
+ }
+ archiveDir->copyTo(destDir);
+ archive.close();
+
+ return true;
+}
+
+bool
+KexiNewStuff::createUploadFile(const QString &)
+{
+ return true;
+}
+
+#endif
diff --git a/kexi/main/kexinewstuff.h b/kexi/main/kexinewstuff.h
new file mode 100644
index 00000000..0af25276
--- /dev/null
+++ b/kexi/main/kexinewstuff.h
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_KNEWSTUFF
+
+#ifndef KEXINEWSTUFF_H
+#define KEXINEWSTUFF_H
+
+#include "knewstuff/knewstuff.h"
+
+class KexiNewStuff : public KNewStuff
+{
+ public:
+ KexiNewStuff(QWidget *parent);
+ virtual ~KexiNewStuff();
+
+ virtual bool install( const QString &fileName );
+ virtual bool createUploadFile( const QString &fileName );
+
+ //KNS::Engine* customEngine() { return KNewStuff::engine(); }
+};
+
+#endif
+
+#endif //HAVE_KNEWSTUFF
diff --git a/kexi/main/kexistatusbar.cpp b/kexi/main/kexistatusbar.cpp
new file mode 100644
index 00000000..c05f0eeb
--- /dev/null
+++ b/kexi/main/kexistatusbar.cpp
@@ -0,0 +1,145 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and,or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+ Loosely based on kdevelop/src/statusbar.cpp
+ Copyright (C) 2001 by Bernd Gehrmann <bernd@kdevelop.org>
+*/
+
+#include "kexistatusbar.h"
+
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qfontmetrics.h>
+
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kparts/part.h>
+
+#if KexiStatusBar_KTEXTEDITOR_USED
+#include <ktexteditor/viewcursorinterface.h>
+#include <ktexteditor/viewstatusmsginterface.h>
+#endif
+
+KexiStatusBar::KexiStatusBar(QWidget *parent, const char *name)
+ : KStatusBar(parent, name)
+#if KexiStatusBar_KTEXTEDITOR_USED
+ , m_cursorIface(0)
+#endif
+ , m_activePart(0)
+{
+ int id = 0;
+ m_msgID = id++;
+ insertItem("", m_msgID, 1, true);
+
+ m_readOnlyID = id++;
+ insertFixedItem(i18n("Read only"), m_readOnlyID, true);
+ setReadOnlyFlag(false);
+
+// @todo
+// connect(PartController::getInstance(), SIGNAL(activePartChanged(KParts::Part*)),
+// this, SLOT(activePartChanged(KParts::Part*)));
+
+ /// @todo remove parts from the map on PartRemoved() ?
+}
+
+
+KexiStatusBar::~KexiStatusBar()
+{
+}
+
+void KexiStatusBar::activePartChanged(KParts::Part *part)
+{
+ if ( m_activePart && m_activePart->widget() )
+ disconnect( m_activePart->widget(), 0, this, 0 );
+
+ m_activePart = part;
+#if KexiStatusBar_KTEXTEDITOR_USED
+ m_cursorIface = 0;
+ m_viewmsgIface = 0;
+// @todo
+ if (part && part->widget()) {
+ if ((m_viewmsgIface = dynamic_cast<KTextEditor::ViewStatusMsgInterface*>(part->widget()))) {
+ connect( part->widget(), SIGNAL( viewStatusMsg( const QString & ) ),
+ this, SLOT( setStatus( const QString & ) ) );
+
+# if KDE_VERSION < KDE_MAKE_VERSION(3,1,90)
+ changeItem(m_map[ m_activePart ], m_msgID);
+// m_status->setText( m_map[ m_activePart ] );
+# endif
+ }
+ else if ((m_cursorIface = dynamic_cast<KTextEditor::ViewCursorInterface*>(part->widget()))) {
+ connect(part->widget(), SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
+ cursorPositionChanged();
+ }
+ else {
+ // we can't produce any status data, hide the status box
+ changeItem("", m_msgID);
+ }
+ }
+#endif
+}
+
+
+void KexiStatusBar::cursorPositionChanged()
+{
+#if KexiStatusBar_KTEXTEDITOR_USED
+ if (m_cursorIface)
+ {
+ uint line, col;
+ m_cursorIface->cursorPosition(&line, &col);
+ setCursorPosition(line, col);
+ }
+#endif
+}
+
+void KexiStatusBar::setStatus(const QString &str)
+{
+ kdDebug() << "KexiStatusBar::setStatus(" << str << ")" << endl;
+// m_status->setText(str);
+ changeItem(str, m_msgID);
+
+#if defined(KDE_MAKE_VERSION)
+# if KDE_VERSION < KDE_MAKE_VERSION(3,1,90)
+ m_map[m_activePart] = str;
+# endif
+#endif
+}
+
+void KexiStatusBar::setCursorPosition(int line, int col)
+{
+// m_status->setText(i18n(" Line: %1 Col: %2 ").arg(line+1).arg(col));
+ changeItem(i18n(" Line: %1 Col: %2 ").arg(line+1).arg(col), m_msgID);
+}
+
+/*void KexiStatusBar::addWidget ( QWidget *widget, int stretch, bool permanent)
+{
+ KStatusBar::addWidget(widget,stretch,permanent);
+
+ if(widget->sizeHint().height() + 4 > height())
+ setFixedHeight(widget->sizeHint().height() + 4);
+}*/
+
+void KexiStatusBar::setReadOnlyFlag(bool readOnly)
+{
+ changeItem(readOnly ? i18n("Read only") : QString::null, m_readOnlyID);
+}
+
+#include "kexistatusbar.moc"
diff --git a/kexi/main/kexistatusbar.h b/kexi/main/kexistatusbar.h
new file mode 100644
index 00000000..eec24932
--- /dev/null
+++ b/kexi/main/kexistatusbar.h
@@ -0,0 +1,77 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and,or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+ Loosely based on kdevelop/src/statusbar.h
+ Copyright (C) 2001 by Bernd Gehrmann <bernd@kdevelop.org>
+*/
+
+#ifndef KEXISTATUSBAR_H
+#define KEXISTATUSBAR_H
+
+//temporary
+#define KexiStatusBar_KTEXTEDITOR_USED 0
+
+#include <kdeversion.h>
+#include <kstatusbar.h>
+#include <qmap.h>
+
+class QLabel;
+
+#if KexiStatusBar_KTEXTEDITOR_USED
+namespace KTextEditor { class ViewStatusMsgInterface; }
+namespace KTextEditor { class ViewCursorInterface; }
+#endif
+namespace KParts { class Part; }
+
+class KexiStatusBar : public KStatusBar
+{
+ Q_OBJECT
+ public:
+ KexiStatusBar( QWidget *parent=0, const char *name=0 );
+ virtual ~KexiStatusBar();
+// virtual void addWidget( QWidget *widget, int stretch = 0, bool permanent = false);
+
+ public slots:
+ virtual void setStatus(const QString &str);
+ virtual void setReadOnlyFlag(bool readOnly);
+
+ protected slots:
+ virtual void cursorPositionChanged();
+ virtual void activePartChanged(KParts::Part *part);
+ virtual void setCursorPosition(int line, int col);
+
+ protected:
+ int m_msgID, m_readOnlyID;
+// QLabel *m_status, *m_readOnlyStatus;
+
+#if KexiStatusBar_KTEXTEDITOR_USED
+ KTextEditor::ViewCursorInterface * m_cursorIface;
+ KTextEditor::ViewStatusMsgInterface * m_viewmsgIface;
+#endif
+ KParts::Part *m_activePart;
+
+// still hoping for a fix for KDE-3.1
+#if defined(KDE_MAKE_VERSION)
+# if KDE_VERSION < KDE_MAKE_VERSION(3,1,90)
+ QMap<KParts::Part*, QString> m_map;
+# endif
+#endif
+};
+
+#endif
+
diff --git a/kexi/main/ksplitter.h b/kexi/main/ksplitter.h
new file mode 100644
index 00000000..db72ec88
--- /dev/null
+++ b/kexi/main/ksplitter.h
@@ -0,0 +1,256 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Copyright (C) 2005 Dominik Haumann <dhdev@gmx.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+/*
+ IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition
+*/
+
+#ifndef KDOCKWIDGET_PRIVATE_H
+#define KDOCKWIDGET_PRIVATE_H
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+
+#include <kdeversion.h>
+
+#ifndef NO_KDE2
+#include <netwm_def.h>
+#endif
+
+class QFrame;
+class KDockContainer;
+class KDockWidget;
+
+
+/**
+ * Like QSplitter but specially designed for dockwidgets stuff.
+ * @internal
+ *
+ * @author Max Judin.
+ */
+class KDockSplitter : public QWidget
+{
+ //Q_OBJECT
+public:
+ /**
+ * Constructor.
+ * @param parent parent widget
+ * @param name name
+ * @param orient orientation. Either @p Vertical or @p Horizontal
+ * @param pos procentual position of the splitter. Must be int [0...100].
+ */
+ KDockSplitter(QWidget *parent= 0, const char *name= 0, Orientation orient= Vertical, int pos= 50);
+ virtual ~KDockSplitter(){};
+
+ /**
+ * Initialize the splitter. If @p c0 or @p c1 is 0L the child will not
+ * be replaced. So if you want to change @p c1 and not change c0, you'd
+ * call @p activate(0L,new_widget);
+ *
+ * @param c0 the widget on top/left
+ * @param c1 the widget on borrom/right
+ */
+ void activate(QWidget *c0, QWidget *c1 = 0L);
+ /**
+ * Disables the splitter.
+ */
+ void deactivate();
+
+ /**
+ * Return the separator position in percent (%), so the range is [0..100]
+ * @return separator position in percent
+ */
+ int separatorPosInPercent()
+#if KDE_IS_VERSION(3,4,89)
+ ;
+#else
+ {
+// kdDebug() << "^^^^^^^^^^^^^^^^^^^^^ separatorPosInPercent() " << separatorPos() / (factor/100) << " " << separatorPos() / 100 << endl;
+ return separatorPos() / 100;
+ }
+#endif
+ /**
+ * Set the separator position in percent (%), so the range must be [0..100]
+ * @param percent separator position in percent
+ */
+ void setSeparatorPosInPercent(int percent)
+#if KDE_IS_VERSION(3,4,89)
+ ;
+#else
+ {
+// kdDebug() << "^^^^^^^^^^^^^^^^^^^^^ setSeparatorPosInPercent() " << percent << " " << separatorPos() / 100 << endl;
+ setSeparatorPos( percent * 100, false );
+ }
+#endif
+
+ /**
+ * Return the separator position in the range [0..100000]
+ * To get the separator position in procent (%), call
+ * @p separatorPositionInPercent()!
+ *
+ * @return high resolution separator position in range [0..100000],
+ * where 100000 is 100%.
+ */
+ int separatorPos() const;
+ /**
+ * set separator position.
+ * @param pos the separator position in range [0..100000]. 100000 is 100%.
+ * @param do_resize true by default
+ */
+ void setSeparatorPos(int pos, bool do_resize = true);
+ /**
+ * For usage from outside.
+ * If the splitter is in fixed position when called,
+ * the value of @p pos will be saved and used when the splitter
+ * is restored.
+ * If @p do_resize is true, the size will be changed unless the splitter
+ * is in fixed mode.
+ */
+ // ### please come up with a nicer name
+ void setSeparatorPosX(int pos, bool do_resize=false);
+
+ /**
+ * The eventfilter installed on the @p divider processes
+ * all splitter resizing events.
+ */
+ virtual bool eventFilter(QObject *, QEvent *);
+ virtual bool event( QEvent * );
+
+ /**
+ * @return the top/left child widget.
+ */
+ QWidget* getFirst() const { return child0; }
+ /**
+ * @return the bottom/right child widget.
+ */
+ QWidget* getLast() const { return child1; }
+ /**
+ * If @p w is child0, return child1, otherwise child0.
+ * @return the other child widget
+ */
+ QWidget* getAnother( QWidget* w ) const;
+ void updateName();
+
+ /**
+ * Set opaque flag.
+ * @param b if true, both child widgets are resized immediately,
+ * if false, the widgets only resize on MouseUpEvent.
+ */
+ void setOpaqueResize(bool b=true);
+ bool opaqueResize() const;
+
+ /**
+ * If @p b is true, the splitter will keep its size on resize events.
+ * If no @p KDockContainer is around, always the left child0 will be fixed size.
+ */
+ void setKeepSize(bool b=true);
+ bool keepSize() const;
+
+
+ void setForcedFixedWidth(KDockWidget *dw,int w);
+ void setForcedFixedHeight(KDockWidget *dw,int h);
+ void restoreFromForcedFixedSize(KDockWidget *dw);
+
+ /**
+ * The orientation is either @p Horizontal or @p Vertical.
+ */
+ Orientation orientation(){return m_orientation;}
+
+protected:
+ friend class KDockContainer;
+ /**
+ * Make sure the splitter position is not out of bounds.
+ * @param position the current position
+ * @return a (new) valid splitter position.
+ */
+ int checkValue(int position) const;
+ /**
+ * Make sure the splitter position is not out of bounds. It has
+ * to honor all child widgets' mimimumSize.
+ * @param position current divider position
+ * @param child the overlapping child
+ * @return the (new) splitter position.
+ */
+ int checkValueOverlapped(int position, QWidget* child) const;
+
+ /**
+ * The resize event resizes @p child0, @p child1 and the @p divider.
+ * The new sizes are dependant of
+ * - whether @p child0 or @p child1 is a KDockContainer
+ * - the current mode which may be
+ * - Closed
+ * - Overlapped (opened)
+ * - Nonoverlap (opened)
+ * .
+ * .
+ * So there are 3*2=6 different modes we have to face.
+ * @param ev the resize Event. If @p ev=0L the user changed
+ * the mode (for example from overlap to nonoverlap mode).
+ */
+ virtual void resizeEvent(QResizeEvent *ev);
+
+/*
+protected slots:
+ void delayedResize();*/
+
+private:
+ /**
+ * updates the minimum and maximun sizes for the KDockSplitter.
+ * The sizes depend on the minimum and maximum sizes of the two child
+ * widgets.
+ */
+ void setupMinMaxSize();
+ /**
+ * child0 and child1 contain the embedded widgets. They are always valid
+ * so no need to make pointer checks.
+ * child[01]->getWidget() may be KDockContainer.
+ */
+ QWidget *child0, *child1;
+ Orientation m_orientation;
+ /**
+ * If initialised is true, the divider!=0L. If false, the divider==0L!
+ */
+ bool initialised;
+ /**
+ * The splitter controller which is between child0 and child1.
+ * Its size is 4 pixel.
+ */
+ QFrame* divider;
+ /**
+ * @p xpos and @p savedXPos represent the current divider position.
+ * If the orientation is Horizontal @p xpos actually is "ypos". So
+ * do not get confused only because of the 'x'.
+ *
+ * xpos and savedXPos are internally high resolution. So *not* 0..100%
+ * but 0..100000=100%. This fixes rounding bugs. In fact, this should
+ * be a double, but due to binary compatibility we can not change this
+ * as we would have to change it in all kdockwidgets.
+ */
+ int xpos, savedXPos;
+ bool mOpaqueResize, mKeepSize;
+ int fixedWidth0,fixedWidth1;
+ int fixedHeight0,fixedHeight1;
+ bool m_dontRecalc;
+ /**
+ * resolution factor, 0 = 0%, 100000=100%
+ */
+ static const int factor = 100000;
+};
+
+#endif
diff --git a/kexi/main/printing/Makefile.am b/kexi/main/printing/Makefile.am
new file mode 100644
index 00000000..a9d49a54
--- /dev/null
+++ b/kexi/main/printing/Makefile.am
@@ -0,0 +1,32 @@
+include $(top_srcdir)/kexi/Makefile.global
+
+noinst_LTLIBRARIES = libkeximainprinting.la
+
+libkeximainprinting_la_SOURCES = \
+kexisimpleprintingengine.cpp \
+kexisimpleprintingpart.cpp \
+kexisimpleprintingpagesetupbase.ui \
+kexisimpleprintingpagesetup.cpp \
+kexisimpleprintpreviewwindow.cpp
+
+noinst_HEADERS = kexisimpleprintpreviewwindow_p.h
+
+libkeximainprinting_la_LDFLAGS = $(all_libraries) -Wnounresolved
+libkeximainprinting_la_LIBADD = \
+ $(top_builddir)/lib/kofficecore/libkofficecore.la \
+ $(top_builddir)/lib/kofficeui/libkofficeui.la \
+ ../../widget/libkexiextendedwidgets.la
+
+libkeximainprinting_la_METASOURCES = AUTO
+
+SUBDIRS = .
+
+# set the include path for X, qt and KDE
+
+INCLUDES= -I$(top_srcdir)/kexi -I$(top_srcdir)/kexi/main/printing \
+ -I$(top_srcdir)/kexi/core -I$(top_srcdir)/kexi/widget \
+ -I$(top_builddir)/lib/kofficeui -I$(top_srcdir)/lib/kofficeui \
+ -I$(top_srcdir)/lib/kofficecore \
+ -I$(top_builddir)/kexi/widget $(all_includes)
+
+#KDE_CXXFLAGS += -DSIMPLE_KOLIBS -DKOFFICECORE_EXPORT= -DKOFFICEUI_EXPORT=
diff --git a/kexi/main/printing/kexisimpleprintingengine.cpp b/kexi/main/printing/kexisimpleprintingengine.cpp
new file mode 100644
index 00000000..e021c912
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingengine.cpp
@@ -0,0 +1,558 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kexisimpleprintingengine.h"
+
+#include <core/keximainwindow.h>
+#include <kexiutils/utils.h>
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kfontdialog.h>
+#include <kurllabel.h>
+#include <kdebug.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qcheckbox.h>
+#include <qwhatsthis.h>
+#include <qpaintdevicemetrics.h>
+#include <qimage.h>
+
+#include <kexiutils/tristate.h>
+#include <kexidb/connection.h>
+#include <kexidb/tableschema.h>
+#include <kexidb/cursor.h>
+#include <kexidb/utils.h>
+#include <kexidb/queryschema.h>
+
+KexiSimplePrintingSettings::KexiSimplePrintingSettings()
+{
+ pageLayout = KoPageLayout::standardLayout();
+ addPageNumbers = true;
+ addDateAndTime = true;
+ addTableBorders = false;
+ pageTitleFont = kapp->font();
+ pageTitleFont.setPointSizeFloat( (double)QFontInfo(pageTitleFont).pointSize()*1.5 );
+ pageTitleFont.setBold(true);
+}
+
+KexiSimplePrintingSettings::~KexiSimplePrintingSettings()
+{
+}
+
+KexiSimplePrintingSettings KexiSimplePrintingSettings::load()
+{
+ KexiSimplePrintingSettings settings; //this will set defaults
+
+ KConfig *config = kapp->config();
+ config->setGroup("Simple Printing");
+ if (config->hasKey("pageTitleFont"))
+ settings.pageTitleFont = config->readFontEntry("pageTitleFont");
+//! @todo system default?
+ if (config->hasKey("pageFormat"))
+ settings.pageLayout.format = KoPageFormat::formatFromString(
+ config->readEntry("pageFormat" ) );
+ if (config->readEntry("pageOrientation", "portrait").lower()=="landscape")
+ settings.pageLayout.orientation = PG_LANDSCAPE;
+ else
+ settings.pageLayout.orientation = PG_PORTRAIT;
+ if (config->hasKey("pageWidth"))
+ settings.pageLayout.ptWidth = config->readDoubleNumEntry("pageWidth");
+ if (config->hasKey("pageHeight"))
+ settings.pageLayout.ptHeight = config->readDoubleNumEntry("pageHeight");
+ if (config->hasKey("pageLeftMargin"))
+ settings.pageLayout.ptLeft = config->readDoubleNumEntry("pageLeftMargin");
+ if (config->hasKey("pageRightMargin"))
+ settings.pageLayout.ptRight = config->readDoubleNumEntry("pageRightMargin");
+ if (config->hasKey("pageTopMargin"))
+ settings.pageLayout.ptTop = config->readDoubleNumEntry("pageTopMargin");
+ if (config->hasKey("pageBottomMargin"))
+ settings.pageLayout.ptBottom = config->readDoubleNumEntry("pageBottomMargin");
+ settings.addPageNumbers = config->readBoolEntry("addPageNumbersToPage", true);
+ settings.addDateAndTime = config->readBoolEntry("addDateAndTimePage", true);
+ settings.addTableBorders = config->readBoolEntry("addTableBorders", false);
+ return settings;
+}
+
+void KexiSimplePrintingSettings::save()
+{
+ KConfig *config = kapp->config();
+ config->setGroup("Simple Printing");
+ config->writeEntry( "pageTitleFont", pageTitleFont );
+ config->writeEntry( "pageFormat", KoPageFormat::formatString( pageLayout.format ) );
+ config->writeEntry("pageOrientation",
+ pageLayout.orientation == PG_PORTRAIT ? "portrait" : "landscape");
+ config->writeEntry("pageWidth", pageLayout.ptWidth);
+ config->writeEntry("pageHeight", pageLayout.ptHeight);
+ config->writeEntry("pageLeftMargin", pageLayout.ptLeft);
+ config->writeEntry("pageRightMargin", pageLayout.ptRight);
+ config->writeEntry("pageTopMargin", pageLayout.ptTop);
+ config->writeEntry("pageBottomMargin", pageLayout.ptBottom);
+ config->writeEntry("addPageNumbersToPage", addPageNumbers);
+ config->writeEntry("addDateAndTimePage", addDateAndTime);
+ config->writeEntry("addTableBorders", addTableBorders);
+ config->sync();
+}
+
+//------------------------
+
+KexiSimplePrintingEngine::KexiSimplePrintingEngine(
+ const KexiSimplePrintingSettings& settings, QObject* parent)
+ : QObject(parent, "KexiSimplePrintingEngine")
+ , m_settings(&settings)
+ , m_pdm(0)
+{
+ m_cursor = 0;
+ m_data = 0;
+ m_visibleFieldsCount = 0;
+ m_dataOffsets.setAutoDelete(true);
+ clear();
+}
+
+KexiSimplePrintingEngine::~KexiSimplePrintingEngine()
+{
+ done();
+}
+
+bool KexiSimplePrintingEngine::init(KexiDB::Connection& conn,
+ KexiDB::TableOrQuerySchema& tableOrQuery, const QString& titleText, QString& errorMessage)
+{
+ errorMessage = QString::null;
+ done();
+ m_headerText = titleText; //tableOrQuery.captionOrName();
+
+ //open data source
+ KexiDB::QuerySchema *query = 0;
+ if (tableOrQuery.table())
+ query = tableOrQuery.table()->query(); //all rows
+ else
+ query = tableOrQuery.query();
+ if (!query) {
+ errorMessage = i18n("Could not load data from table or query.");
+ return false;
+ }
+
+ m_cursor = conn.executeQuery(*query);
+ if (!m_cursor) {
+ conn.debugError();
+ return false;
+ }
+ bool ok = !m_cursor->error();
+ if (ok) {
+ m_data = new KexiTableViewData(m_cursor);
+//! @todo primitive: data should be loaded on demand
+ m_data->preloadAllRows();
+ m_fieldsExpanded = query->fieldsExpanded( KexiDB::QuerySchema::WithInternalFields );
+ m_visibleFieldsCount = m_cursor->query()->fieldsExpanded().count(); //real fields count without internals
+ }
+ else {
+ conn.debugError();
+ }
+ m_eof = !ok || m_data->count() == 0;
+ conn.deleteCursor(m_cursor);
+ m_cursor = 0;
+ return ok;
+}
+
+bool KexiSimplePrintingEngine::done()
+{
+ bool result = true;
+ if (m_cursor && (m_cursor->error() || !m_cursor->connection()->deleteCursor(m_cursor))) {
+ m_cursor->debugError();
+ result = false;
+ }
+ m_cursor = 0;
+ delete m_data;
+ m_data = 0;
+ m_pagesCount = 0;
+ m_paintInitialized = false;
+ m_fieldsExpanded.clear();
+ m_visibleFieldsCount = 0;
+ return result;
+}
+
+void KexiSimplePrintingEngine::clear()
+{
+ m_eof = false;
+ m_pagesCount = 0;
+ m_dataOffsets.clear();
+ m_dataOffsets.append(new uint(0));
+ m_paintInitialized = false;
+}
+
+void KexiSimplePrintingEngine::paintPage(int pageNumber, QPainter& painter, bool paint)
+{
+ uint offset = 0;
+ if (pageNumber < (int)m_dataOffsets.count()) {
+ offset = *m_dataOffsets.at(pageNumber);
+ }
+
+ double y = 0.0;
+
+ const bool printing = painter.device()->devType() == QInternal::Printer;
+ m_SCALE = printing ? 1 : 20;
+
+ double w, h;
+ m_pdm = QPaintDeviceMetrics( painter.device() );
+
+ if (dynamic_cast<QWidget*>(painter.device())) {
+ w = dynamic_cast<QWidget*>(painter.device())->width() * m_SCALE;
+ h = dynamic_cast<QWidget*>(painter.device())->height() * m_SCALE;
+ }
+ else if (dynamic_cast<QPixmap*>(painter.device())) {
+ w = dynamic_cast<QPixmap*>(painter.device())->width() * m_SCALE;
+ h = dynamic_cast<QPixmap*>(painter.device())->height() * m_SCALE;
+ }
+ else {//KPrinter...
+ w = m_pdm.widthMM();
+ h = m_pdm.heightMM();
+ }
+
+ if (!m_paintInitialized) {
+ m_paintInitialized = true;
+
+ double widthMM = KoPageFormat::width(
+ m_settings->pageLayout.format, m_settings->pageLayout.orientation);
+ double heightMM = KoPageFormat::height(
+ m_settings->pageLayout.format, m_settings->pageLayout.orientation);
+
+ m_dpiY = m_pdm.logicalDpiY();
+ m_dpiX = m_pdm.logicalDpiX();
+#ifdef Q_WS_WIN //fix for 120dpi
+ if (!printing) {
+ m_dpiY = 96;
+ m_dpiX = 96;
+// m_dpiY = 86;
+// m_dpiX = 86;
+ }
+#endif
+ double pdWidthMM = m_pdm.widthMM();
+ double pdHeightMM = m_pdm.heightMM();
+
+// double screenF;
+// screenF = 1.0;
+
+ m_leftMargin = POINT_TO_INCH(m_settings->pageLayout.ptLeft)*m_dpiX * (double)m_SCALE;//* screenF;
+ m_rightMargin = POINT_TO_INCH(m_settings->pageLayout.ptRight)*m_dpiX * (double)m_SCALE;//* screenF;
+ m_topMargin = POINT_TO_INCH(m_settings->pageLayout.ptTop)*m_dpiY * (double)m_SCALE;//* screenF;
+ m_bottomMargin = POINT_TO_INCH(m_settings->pageLayout.ptBottom)*m_dpiY * (double)m_SCALE;//* screenF;
+
+ m_fx = widthMM / (pdWidthMM);// * screenF);
+ m_fy = heightMM / (pdHeightMM);// * screenF);
+
+ //screen only
+ // painter.fillRect(QRect(0,0,w,h), QBrush(white));
+ m_pageWidth = uint( m_fx*double(m_pdm.width()) * m_SCALE - m_leftMargin - m_rightMargin );
+ m_pageHeight = uint( m_fy*double(m_pdm.height()) * m_SCALE - m_topMargin - m_bottomMargin );
+ m_headerFont = m_settings->pageTitleFont;
+ if(!printing) {
+ int pixelSize = int( POINT_TO_INCH((double)QFontInfo(m_headerFont).pointSize())*m_dpiX ) * m_SCALE;
+ m_headerFont.setPixelSize(pixelSize);
+ }
+
+//! @todo add setting
+ m_mainFont = kapp->font();
+ if(!printing) {
+ int pixelSize = int( POINT_TO_INCH(m_mainFont.pointSizeFloat())*m_dpiX )
+ * m_SCALE;
+ m_mainFont.setPixelSize(pixelSize);
+ }
+ painter.setFont(m_mainFont);
+
+ m_dateTimeText = KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(),
+ true, false);
+ m_dateTimeWidth = painter.fontMetrics().width(m_dateTimeText+" ");
+ m_mainLineSpacing = painter.fontMetrics().lineSpacing();
+ m_footerHeight = m_mainLineSpacing * 2; //2 lines
+ painter.setFont(m_headerFont);
+ m_headerTextRect = painter.fontMetrics().boundingRect(
+ (int)m_leftMargin, (int)m_topMargin,
+ m_pageWidth - m_dateTimeWidth,
+ m_pageHeight, Qt::AlignAuto|Qt::WordBreak, m_headerText);
+ m_headerTextRect.setRight(m_headerTextRect.right()+10);
+ m_headerTextRect.setWidth(
+ QMIN(int(m_pageWidth - m_dateTimeWidth), m_headerTextRect.width()));
+
+ //--compute max width of field names
+ m_maxFieldNameWidth = 0;
+
+ painter.setFont(m_mainFont);
+ for (uint i=0; i < m_visibleFieldsCount; i++) {
+ const int newW =
+ painter.fontMetrics().width(m_fieldsExpanded[i]->captionOrAliasOrName()+":");
+// kdDebug() << "row"<<i<<": "<<m_fieldsExpanded[i]->captionOrAliasOrName()<<" "
+// << newW <<endl;
+ if (m_maxFieldNameWidth < newW)
+ m_maxFieldNameWidth = newW;
+ }
+ m_maxFieldNameWidth += painter.fontMetrics().width("ww"); //more space
+ }
+
+ //screen only
+ if(!printing) {
+ painter.setWindow(0, 0, int(w*m_fx), int(h*m_fy));
+ }
+
+ //paint header
+ painter.setFont(m_headerFont);
+ if (paint) {
+ painter.drawText(m_headerTextRect, Qt::AlignAuto|Qt::WordBreak, m_headerText);
+ }
+ painter.setFont(m_mainFont);
+ if (paint) {
+ painter.drawText((int)m_leftMargin + m_pageWidth - m_dateTimeWidth,
+ (int)m_topMargin, m_dateTimeWidth,
+ m_headerTextRect.height(), Qt::AlignRight, m_dateTimeText);
+ //footer
+ QString pageNumString;
+ if (m_pagesCount>0)
+ pageNumString = i18n("Page (number) of (total)", "Page %1 of %2")
+ .arg(pageNumber+1).arg(m_pagesCount);
+ else
+ pageNumString = i18n("Page %1").arg(pageNumber+1);
+ painter.drawText((int)m_leftMargin,
+ (int)m_topMargin + m_pageHeight - m_mainLineSpacing,
+ m_pageWidth, m_mainLineSpacing,
+ Qt::AlignRight | Qt::AlignBottom, pageNumString);
+ painter.drawLine((int)m_leftMargin,
+ (int)m_topMargin + m_pageHeight - m_mainLineSpacing*3/2,
+ (int)m_leftMargin + m_pageWidth,
+ (int)m_topMargin + m_pageHeight - m_mainLineSpacing*3/2);
+ }
+ y = (double)m_topMargin + (double)m_headerTextRect.height() + double(m_mainLineSpacing)/2;
+ if (!m_settings->addTableBorders) {
+ //separator line
+ if (paint)
+ painter.drawLine((int)m_leftMargin, (int)y, (int)m_leftMargin + m_pageWidth-1, (int)y);
+ y += (double)m_mainLineSpacing;
+ }
+
+ //--print records
+ KexiDB::RowData row;
+ KexiTableItem *item;
+// const uint count = m_fieldsExpanded.count();
+// const uint count = m_cursor->query()->fieldsExpanded().count(); //real fields count without internals
+ const uint rows = m_data->count();
+ const int cellMargin = m_settings->addTableBorders ?
+ painter.fontMetrics().width("i") : 0;
+ uint paintedRows = 0;
+ for (;offset < rows; ++offset) {
+ item = m_data->at(offset);
+
+ //compute height of this record
+ double newY = y;
+ paintRecord(painter, item, cellMargin, newY, paintedRows, false, printing);
+// if ((int(m_topMargin + m_pageHeight-newY-m_footerHeight)) < 0 /*(1)*/ && paintedRows > 0/*(2)*/) {
+ if (newY > (m_topMargin + m_pageHeight - m_mainLineSpacing*2 + m_mainLineSpacing) /*(1)*/ && paintedRows > 0/*(2)*/) {
+ //(1) do not break records between pages
+ //(2) but paint at least one record
+//! @todo break large records anyway...
+ break;
+ }
+/* if (int(count * m_mainLineSpacing) > int(m_topMargin + m_pageHeight-(int)y-m_footerHeight))
+ {
+ //do not break records between pages
+ break;
+ }*/
+// kdDebug() << " -------- " << y << " / " << m_pageHeight << endl;
+ if (paint)
+ paintRecord(painter, item, cellMargin, y, paintedRows, paint, printing);
+ else
+ y = newY; //speedup
+ paintedRows++;
+ }
+
+ if (int(m_dataOffsets.count()-1)==pageNumber) {//this was next page
+ m_dataOffsets.append(new uint(offset));
+ }
+ m_eof = offset == rows;
+}
+
+void KexiSimplePrintingEngine::paintRecord(QPainter& painter, KexiTableItem *item,
+ int cellMargin, double &y, uint paintedRows, bool paint, bool printing)
+{
+ if (paintedRows>0 && !m_settings->addTableBorders) {//separator
+ if (paint) {
+ painter.setPen(Qt::darkGray);
+ painter.drawLine(
+ int(m_leftMargin), int( y-(double)m_mainLineSpacing ),
+ int(m_leftMargin)+m_pageWidth-1, int(y-(double)m_mainLineSpacing));
+ painter.setPen(Qt::black);
+ }
+ }
+
+ for (uint i=0; i<m_visibleFieldsCount; i++) {
+// kdDebug() << "row"<<i<<": "<<row.at(i).toString()<<endl;
+ if (paint) {
+ painter.drawText(
+ (int)m_leftMargin+cellMargin, (int)y, m_maxFieldNameWidth-cellMargin*2, m_mainLineSpacing,
+ Qt::AlignTop, m_fieldsExpanded[i]->captionOrAliasOrName()
+ + (m_settings->addTableBorders ? "" : ":"));
+ }
+ QString text;
+//! @todo optimize like in KexiCSVExport::exportData()
+ //get real column and real index to get the visible value
+ KexiDB::QueryColumnInfo* ci;
+ int indexForVisibleLookupValue = m_fieldsExpanded[i]->indexForVisibleLookupValue();
+ if (-1 != indexForVisibleLookupValue && indexForVisibleLookupValue < (int)item->count()/*sanity*/)
+ ci = m_fieldsExpanded[ indexForVisibleLookupValue ];
+ else {
+ ci = m_fieldsExpanded[ i ];
+ indexForVisibleLookupValue = i;
+ }
+
+ QVariant v(item->at( indexForVisibleLookupValue ));
+ KexiDB::Field::Type ftype = ci->field->type();
+ QRect rect( (int)m_leftMargin + m_maxFieldNameWidth + cellMargin, (int)y,
+ m_pageWidth - m_maxFieldNameWidth - cellMargin*2, m_pageHeight - (int)y);
+
+ if (v.isNull() || !v.isValid()) {
+ //nothing to do
+ }
+//! todo inherit format
+ else if (ftype==KexiDB::Field::DateTime) {
+ QDateTime dt(v.toDateTime());
+ if (dt.isValid())
+ text = KGlobal::locale()->formatDateTime(dt);
+ }
+//! todo inherit format
+ else if (ftype==KexiDB::Field::Date) {
+ QDate date(v.toDate());
+ if (date.isValid())
+ text = KGlobal::locale()->formatDate(date, true/*short*/);
+ }
+//! todo inherit format
+ else if (ftype==KexiDB::Field::Time) {
+ QTime time(v.toTime());
+ if (time.isValid())
+ text = KGlobal::locale()->formatTime(time);
+ }
+//! todo currency, decimal...
+ else if (ci->field->isFPNumericType())
+ text = KGlobal::locale()->formatNumber(v.toDouble());
+ else if (ftype==KexiDB::Field::Boolean)
+ text = v.toBool()
+ ? i18n("Boolean Yes (true)","Yes") : i18n("Boolean No (false)", "No");
+ else if (ftype==KexiDB::Field::BLOB) {
+ const QByteArray ba( v.toByteArray() );
+ if (!ba.isEmpty()) {
+ QPixmap pixmap(ba);
+#define MAX_PIXMAP_HEIGHT (m_mainLineSpacing * 5)
+ double pixmapHeight = MAX_PIXMAP_HEIGHT;
+ double pixmapWidth = double(MAX_PIXMAP_HEIGHT) * pixmap.width() / (double)pixmap.height();
+ if (pixmapWidth > (double)rect.width()) { //too wide
+ pixmapHeight = pixmapHeight * (double)rect.width() / pixmapWidth;
+ pixmapWidth = rect.width();
+ }
+ rect.setHeight( int( pixmapHeight + m_mainLineSpacing / 2 ) );
+ if (paint && !pixmap.isNull()) {
+ if (printing) {
+ painter.drawPixmap(
+ QRect(rect.x(), rect.y()+m_mainLineSpacing/4,
+ int(pixmapWidth), int(pixmapHeight)), pixmap );
+ }
+ else {// we're just previewing the pixmap, so let's resize it and cache
+ // so redrawing will be faster
+ painter.save();
+ painter.setWindow( // set 1:1 scale to avoid unnecessary image scaling
+ QRect(painter.window().topLeft(),
+ painter.window().size() / (int)m_SCALE ) );
+ painter.drawImage(
+ int(rect.x() / m_SCALE),
+ int( (rect.y()+m_mainLineSpacing/4) / m_SCALE),
+ pixmap.convertToImage().smoothScale(
+ int(pixmapWidth / m_SCALE), int(pixmapHeight / m_SCALE),
+ QImage::ScaleMin ));
+ painter.restore(); // back to m_SCALE:1 scale
+ }
+ }
+ }
+ }
+ else
+ text = v.toString();
+
+ if (ftype!=KexiDB::Field::BLOB || v.isNull() || !v.isValid())
+ rect = QRect( painter.fontMetrics().boundingRect(
+ rect.x(), rect.y(), rect.width(), rect.height(),
+ Qt::AlignAuto|Qt::WordBreak, text) );
+ if (!text.isEmpty() && paint) {
+// kdDebug() << "print engine: painter.drawText: "
+// << rect.x() <<" "<< rect.y() <<" "<< m_pageWidth - m_maxFieldNameWidth - cellMargin*2
+// <<" "<< m_topMargin + m_pageHeight - (int)y <<" "<<m_pageHeight<<" "<<y<<" "<< text << endl;
+ painter.drawText(
+// rect.x(), rect.y(), rect.width(), rect.height(),
+ rect.x(), rect.y(), m_pageWidth - m_maxFieldNameWidth - cellMargin*2,
+ int(m_topMargin + m_pageHeight - (int)y),
+ Qt::AlignTop|Qt::WordBreak, text);
+ }
+ if (m_settings->addTableBorders) {
+ if (paint) {
+ painter.setPen(Qt::darkGray);
+ painter.drawLine(
+ (int)m_leftMargin, rect.top(), (int)m_leftMargin+m_pageWidth-1, rect.top());
+ painter.drawLine(
+ (int)m_leftMargin, rect.top(), (int)m_leftMargin, rect.bottom());
+ painter.drawLine(
+ (int)m_leftMargin+m_pageWidth-1, rect.top(),
+ (int)m_leftMargin+m_pageWidth-1, rect.bottom());
+ painter.drawLine(
+ (int)m_leftMargin+m_maxFieldNameWidth, rect.top(),
+ (int)m_leftMargin+m_maxFieldNameWidth, rect.bottom());
+ painter.setPen(Qt::black);
+ }
+ }
+ y += (double)rect.height();
+ }
+ if (m_settings->addTableBorders) {
+ if (paint) {
+ painter.setPen(Qt::darkGray);
+ painter.drawLine(
+ (int)m_leftMargin, (int)y, (int)m_leftMargin+m_pageWidth-1, (int)y);
+ painter.setPen(Qt::black);
+ }
+ }
+ //record spacing
+ y += double(m_mainLineSpacing)*3.0/2.0;
+// if (m_settings->addTableBorders)
+// y -= m_mainLineSpacing; //a bit less
+}
+
+void KexiSimplePrintingEngine::calculatePagesCount(QPainter& painter)
+{
+ if (m_eof || !m_data) {
+ m_pagesCount = 0;
+ return;
+ }
+
+ uint pageNumber = 0;
+ for(;!m_eof; ++pageNumber) {
+ paintPage(pageNumber, painter, false /* !paint */);
+ }
+ m_pagesCount = pageNumber;
+}
+
+void KexiSimplePrintingEngine::setTitleText(const QString& titleText)
+{
+ m_headerText = titleText;
+}
+
+#include "kexisimpleprintingengine.moc"
diff --git a/kexi/main/printing/kexisimpleprintingengine.h b/kexi/main/printing/kexisimpleprintingengine.h
new file mode 100644
index 00000000..551ed248
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingengine.h
@@ -0,0 +1,130 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KEXISIMPLEPRINTINGENGINE_H
+#define KEXISIMPLEPRINTINGENGINE_H
+
+class KexiSimplePrintingSettings;
+
+#include <kexidb/connection.h>
+#include <kexidb/tableschema.h>
+#include <kexidb/cursor.h>
+#include <kexidb/utils.h>
+#include <kexidb/queryschema.h>
+#include <widget/tableview/kexitableviewdata.h>
+#include <KoPageLayoutDia.h>
+
+#include <qpaintdevicemetrics.h>
+#include <qfontmetrics.h>
+#include <qfont.h>
+
+//! @short Settings data for simple printing engine.
+class KexiSimplePrintingSettings
+{
+ public:
+ KexiSimplePrintingSettings();
+ ~KexiSimplePrintingSettings();
+
+ static KexiSimplePrintingSettings load();
+ void save();
+
+ KoPageLayout pageLayout;
+ KoUnit::Unit unit;
+ QFont pageTitleFont;
+ bool addPageNumbers : 1;
+ bool addDateAndTime : 1;
+ bool addTableBorders : 1;
+};
+
+/*! @short An engine painting data on pages using QPainter.
+ The engine allows for random access to any page. */
+class KexiSimplePrintingEngine : public QObject
+{
+ Q_OBJECT
+
+ public:
+ KexiSimplePrintingEngine( const KexiSimplePrintingSettings& settings, QObject* parent );
+ ~KexiSimplePrintingEngine();
+
+ bool init(KexiDB::Connection& conn, KexiDB::TableOrQuerySchema& tableOrQuery,
+ const QString& titleText, QString& errorMessage);
+
+ void setTitleText(const QString& titleText);
+
+ //! Calculates pafe count that can be later obtained using pagesCount().
+ //! Page count can depend on \a painter (printer/screen) and on printing settings.
+ void calculatePagesCount(QPainter& painter);
+
+ bool done();
+ void clear();
+ const KexiSimplePrintingSettings* settings() const { return m_settings; }
+
+ //! \return true when all records has been painted
+ bool eof() const { return m_eof; }
+
+ //! \return number of pages. Can be used after calculatePagesCount().
+ uint pagesCount() const { return m_pagesCount; }
+
+ //! \return number of painted pages so far.
+ //! If eof() is true, this number is equal to total page count.
+ uint paintedPages() const { return m_dataOffsets.count(); }
+
+ public slots:
+ /*! Paints a page number \a pageNumber (counted from 0) on \a painter.
+ If \a paint is false, drawings are only computed but not painted,
+ so this can be used for calculating page number before printing or previewing. */
+ void paintPage(int pageNumber, QPainter& painter, bool paint = true);
+
+ protected:
+ void paintRecord(QPainter& painter, KexiTableItem *item,
+ int cellMargin, double &y, uint paintedRows, bool paint, bool printing);
+
+ const KexiSimplePrintingSettings* m_settings;
+
+// QPainter* m_painter;
+ QFont m_mainFont, m_headerFont;
+ QPaintDeviceMetrics m_pdm;
+ double m_dpiX, m_dpiY;
+ uint m_pageWidth, m_pageHeight;
+ uint m_SCALE;
+ //QFontMetrics m_headerFM, m_mainFM;
+ KexiDB::Cursor *m_cursor;
+ KexiTableViewData *m_data;
+// KexiTableViewData::Iterator *m_dataIterator;
+ QPtrList<uint> m_dataOffsets;
+ QString m_headerText;
+ QString m_dateTimeText;
+ uint m_dateTimeWidth;
+ QRect m_headerTextRect;
+ int m_maxFieldNameWidth;
+ int m_mainLineSpacing;
+ int m_footerHeight;
+ KexiDB::QueryColumnInfo::Vector m_fieldsExpanded;
+ uint m_visibleFieldsCount;
+ uint m_pagesCount;
+ bool m_eof;
+ bool m_paintInitialized; //!< used by paintPage()
+ double m_leftMargin;
+ double m_rightMargin;
+ double m_topMargin;
+ double m_bottomMargin;
+ double m_fx, m_fy;
+};
+
+#endif
diff --git a/kexi/main/printing/kexisimpleprintingpagesetup.cpp b/kexi/main/printing/kexisimpleprintingpagesetup.cpp
new file mode 100644
index 00000000..5d20f36e
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingpagesetup.cpp
@@ -0,0 +1,550 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "kexisimpleprintingpagesetup.h"
+#include "kexisimpleprintingpagesetupbase.h"
+#include "kexisimpleprintpreviewwindow.h"
+
+#include <core/keximainwindow.h>
+#include <kexiutils/utils.h>
+#include <kexi_version.h>
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kfontdialog.h>
+#include <kurllabel.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <kprinter.h>
+#include <kpushbutton.h>
+#include <kdeversion.h>
+
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qcheckbox.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+
+#include <kexiutils/tristate.h>
+
+KexiSimplePrintingCommand::KexiSimplePrintingCommand(
+ KexiMainWindow* mainWin, int objectId, QObject* parent)
+ : QObject(parent, "KexiSimplePrintCommand")
+ , m_previewEngine(0)
+ , m_mainWin(mainWin)
+ , m_objectId(objectId)
+ , m_previewWindow(0)
+ , m_printPreviewNeedsReloading(false)
+{
+ connect(this, SIGNAL(showPageSetupRequested(KexiPart::Item*)),
+ m_mainWin, SLOT(showPageSetupForItem(KexiPart::Item*)));
+}
+
+KexiSimplePrintingCommand::~KexiSimplePrintingCommand()
+{
+ delete m_previewWindow;
+ delete m_previewEngine;
+// delete m_settings;
+}
+
+
+bool KexiSimplePrintingCommand::print(const KexiSimplePrintingSettings& settings,
+ const QString& aTitleText)
+{
+ m_settings = settings;
+ return print(aTitleText);
+}
+
+bool KexiSimplePrintingCommand::print(const QString& aTitleText)
+{
+ KexiDB::Connection *conn = m_mainWin->project()->dbConnection();
+ KexiDB::TableOrQuerySchema tableOrQuery(conn, m_objectId);
+ if (!tableOrQuery.table() && !tableOrQuery.query()) {
+//! @todo item not found
+ return false;
+ }
+ QString titleText(aTitleText.stripWhiteSpace());
+ if (titleText.isEmpty())
+ titleText = tableOrQuery.captionOrName();
+
+ KexiSimplePrintingEngine engine(m_settings, this);
+ QString errorMessage;
+ if (!engine.init(*conn, tableOrQuery, titleText, errorMessage)) {
+ if (!errorMessage.isEmpty())
+ KMessageBox::sorry(m_mainWin, errorMessage, i18n("Printing"));
+ return false;
+ }
+
+ //setup printing
+#ifdef Q_WS_WIN
+ QPrinter printer(QPrinter::HighResolution);
+ printer.setOrientation( m_settings.pageLayout.orientation == PG_PORTRAIT
+ ? QPrinter::Portrait : QPrinter::Landscape );
+ printer.setPageSize(
+ (QPrinter::PageSize)KoPageFormat::printerPageSize( m_settings.pageLayout.format ) );
+
+ // "chicken-egg" problem:
+ // we cannot use real from/to values in setMinMax() and setFromTo()
+ // because page count is known after obtaining print settings
+ printer.setFromTo(1,1);
+#else
+ KPrinter printer;
+ printer.setOrientation( m_settings.pageLayout.orientation == PG_PORTRAIT
+ ? KPrinter::Portrait : KPrinter::Landscape );
+ printer.setPageSize(
+ (KPrinter::PageSize)KoPageFormat::printerPageSize( m_settings.pageLayout.format ) );
+#endif
+
+ printer.setFullPage(true);
+ QString docName( titleText );
+ printer.setDocName( docName );
+ printer.setCreator(KEXI_APP_NAME);
+ if ( !printer.setup( m_mainWin ) ) {
+ return true;
+ }
+
+ // now we have final settings
+
+//! @todo get printer.pageOrder() (for reversed order requires improved engine)
+ QPainter painter;
+
+ if (!painter.begin(&printer)) {
+//! @todo msg
+ return false;
+ }
+ engine.calculatePagesCount(painter);
+
+ uint loops, loopsPerPage;
+ QValueList<int> pagesToPrint;
+ int fromPage = 0;
+#ifdef Q_WS_WIN
+ int toPage = 0;
+ if (QPrinter::PageRange == printer.printRange()) {
+ fromPage = printer.fromPage();
+ toPage = printer.toPage();
+ }
+ if (fromPage==0 || toPage==0) {
+ fromPage = 0;
+ toPage = (int)engine.pagesCount()-1;
+ }
+ else {
+ fromPage--;
+ if (toPage > (int)engine.pagesCount())
+ toPage = (int)engine.pagesCount();
+ toPage--;
+ }
+ // win32 only supports one range, build the list
+ for (int i = fromPage; i<=toPage; i++) {
+ pagesToPrint.append(i);
+ }
+ // on win32 the OS does perform buffering (only when collation is off, each copy needs to be repeated)
+ loops = 1;
+ loopsPerPage = printer.collateCopies() ? 1 : printer.numCopies();
+#else
+ // on !win32 print QPrinter::numCopies() times (the OS does not perform buffering)
+ pagesToPrint = printer.pageList();
+ kdDebug() << pagesToPrint << endl;
+ if (pagesToPrint.isEmpty()) {
+ fromPage = 0;
+ for (int i = 0; i<(int)engine.pagesCount(); i++) {
+ pagesToPrint.append(i);
+ }
+ }
+ else
+ fromPage = pagesToPrint.first();
+ if (printer.collate()==KPrinter::Collate) {
+ //collation: p1, p2,..pn; p1, p2,..pn; ......; p1, p2,..pn
+ loops = printer.numCopies();
+ loopsPerPage = 1;
+ }
+ else {
+ //no collation: p1, p1, ..., p1; p2, p2, ..., p2; ......; pn, pn,..pn
+ loops = 1;
+ loopsPerPage = printer.numCopies();
+ }
+//! @todo also look at printer.pageSet() option : all/odd/even pages
+#endif
+ // now, total number of printed pages is printer.numCopies()*printer.pageList().count()
+
+ kdDebug() << "printing..." << endl;
+ bool firstPage = true;
+ for (uint copy = 0;copy < loops; copy++) {
+ kdDebug() << "copy " << (copy+1) << " of " << loops << endl;
+ uint pageNumber = fromPage;
+ QValueList<int>::ConstIterator pagesIt = pagesToPrint.constBegin();
+ for(;(int)pageNumber == fromPage || !engine.eof(); ++pageNumber) {
+ kdDebug() << "printing..." << endl;
+ if (pagesIt == pagesToPrint.constEnd()) //no more pages to print
+ break;
+ if ((int)pageNumber < *pagesIt) { //skip pages without printing (needed for computation)
+ engine.paintPage(pageNumber, painter, false);
+ continue;
+ }
+ if (*pagesIt < (int)pageNumber) { //sanity
+ ++pagesIt;
+ continue;
+ }
+ for (uint onePageCounter = 0; onePageCounter < loopsPerPage; onePageCounter++) {
+ if (!firstPage)
+ printer.newPage();
+ else
+ firstPage = false;
+ kdDebug() << "page #" << pageNumber << endl;
+ engine.paintPage(pageNumber, painter);
+ }
+ ++pagesIt;
+ }
+ }
+ kdDebug() << "end of printing." << endl;
+
+ // stop painting, this will automatically send the print data to the printer
+ if (!painter.end())
+ return false;
+
+ if (!engine.done())
+ return false;
+
+ return true;
+}
+
+bool KexiSimplePrintingCommand::showPrintPreview(const KexiSimplePrintingSettings& settings,
+ const QString& aTitleText, bool reload)
+{
+ m_settings = settings;
+ if (!m_previewEngine)
+ m_previewEngine = new KexiSimplePrintingEngine(m_settings, this);
+
+ if (reload)
+ m_printPreviewNeedsReloading = true;
+
+ bool backToPage0 = true;
+ QString titleText(aTitleText.stripWhiteSpace());
+ KexiDB::Connection *conn = m_mainWin->project()->dbConnection();
+ KexiDB::TableOrQuerySchema tableOrQuery(conn, m_objectId);
+ if (!tableOrQuery.table() && !tableOrQuery.query()) {
+//! @todo item not found
+ return false;
+ }
+ if (titleText.isEmpty())
+ titleText = tableOrQuery.captionOrName();
+ if (!m_previewWindow || m_printPreviewNeedsReloading) {
+ QString errorMessage;
+ if (!m_previewEngine->init(
+ *conn, tableOrQuery, titleText, errorMessage)) {
+ if (!errorMessage.isEmpty())
+ KMessageBox::sorry(m_mainWin, errorMessage, i18n("Print Preview"));
+ return false;
+ }
+ }
+ if (!m_previewWindow) {
+ backToPage0 = false;
+ m_previewWindow = new KexiSimplePrintPreviewWindow(
+ *m_previewEngine, tableOrQuery.captionOrName(), 0,
+ Qt::WStyle_Customize|Qt::WStyle_NormalBorder|Qt::WStyle_Title|
+ Qt::WStyle_SysMenu|Qt::WStyle_MinMax|Qt::WStyle_ContextHelp);
+ connect(m_previewWindow, SIGNAL(printRequested()), this, SLOT(print()));
+ connect(m_previewWindow, SIGNAL(pageSetupRequested()), this, SLOT(slotShowPageSetupRequested()));
+ m_previewWindow->show();
+ KDialog::centerOnScreen(m_previewWindow);
+ m_printPreviewNeedsReloading = false;
+ }
+
+ if (m_printPreviewNeedsReloading) {//dirty
+ m_previewEngine->clear();
+//! @todo progress bar...
+ m_previewEngine->setTitleText( titleText );
+ m_previewWindow->setFullWidth();
+ m_previewWindow->updatePagesCount();
+ m_printPreviewNeedsReloading = false;
+ }
+ if (backToPage0)
+ m_previewWindow->goToPage(0);
+ m_previewWindow->show();
+ m_previewWindow->raise();
+// m_previewWindow->setPagesCount(INT_MAX); //will be properly set on demand
+ return true;
+}
+
+void KexiSimplePrintingCommand::slotShowPageSetupRequested()
+{
+ m_mainWin->raise();
+ emit showPageSetupRequested( m_mainWin->project()->item( m_objectId ) );
+}
+
+/*void KexiSimplePrintingCommand::setPrintPreviewNeedsReloading()
+{
+ m_printPreviewNeedsReloading = true;
+}*/
+
+//----------------------------------------------------------
+
+KexiSimplePrintingPageSetup::KexiSimplePrintingPageSetup( KexiMainWindow *mainWin, QWidget *parent,
+ QMap<QString,QString>* args )
+ : KexiViewBase( mainWin, parent, "KexiSimplePrintingPageSetup" )
+ , m_settings( KexiSimplePrintingSettings::load() )
+// , m_command(0)
+{
+ // object to print
+ bool ok = args;
+ int objectId;
+ if (ok)
+ objectId = (*args)["identifier"].toInt();
+ ok = objectId<=0;
+ m_item = mainWin->project()->item( objectId );
+ ok = m_item;
+
+ bool printPreview = false;
+ bool print = false;
+ bool pageSetup = false;
+ if (ok) {
+ printPreview = (*args)["action"]=="printPreview";
+ print = (*args)["action"]=="print";
+ pageSetup = (*args)["action"]=="pageSetup";
+ ok = printPreview || print || pageSetup;
+ }
+
+ // settings
+//! @todo default?
+ m_unit = KLocale::Metric == KGlobal::locale()->measureSystem() ? KoUnit::U_CM : KoUnit::U_INCH;
+
+ // GUI
+ QVBoxLayout *lyr = new QVBoxLayout(this);
+ m_contents = new KexiSimplePrintingPageSetupBase(this, "KexiSimplePrintingPageSetupBase");
+ lyr->addWidget(m_contents);
+
+ setViewWidget(m_contents, true);
+// setFocusPolicy(WheelFocus);
+ m_contents->setFocusProxy(m_contents->headerTitleLineEdit);
+
+ m_contents->printButton->setIconSet( KStdGuiItem::print().iconSet(KIcon::Small) );
+ m_contents->printButton->setText( KStdGuiItem::print().text() );
+ connect(m_contents->printButton, SIGNAL(clicked()), this, SLOT(print()));
+
+ m_contents->printPreviewButton->setIconSet( SmallIconSet("filequickprint") );
+ m_contents->printPreviewButton->setText( i18n("Print Previe&w...") );
+ connect(m_contents->printPreviewButton, SIGNAL(clicked()), this, SLOT(printPreview()));
+
+ m_contents->iconLabel->setFixedWidth(32+6);
+ m_contents->iconLabel->setPixmap( DesktopIcon("document", 32) );
+ QWhatsThis::add(m_contents->headerTitleFontButton, i18n("Changes font for title text."));
+ connect(m_contents->headerTitleFontButton, SIGNAL(clicked()),
+ this, SLOT(slotChangeTitleFont()));
+
+ if (m_item) {
+ m_origCaptionLabelText = m_contents->captionLabel->text();
+ m_contents->headerTitleLineEdit->setText( m_item->captionOrName() );
+ if (m_item->mimeType()=="kexi/query") {
+ m_contents->openDataLink->setText( i18n("Open This Query") );
+ m_origCaptionLabelText = i18n("<h2>Page setup for printing \"%1\" query data</h2>");
+ }
+ m_contents->captionLabel->setText( m_origCaptionLabelText.arg(m_item->name()) );
+ }
+ connect(m_contents->headerTitleLineEdit,SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotTitleTextChanged(const QString&)));
+ m_contents->headerTitleLineEdit->setFont( m_settings.pageTitleFont );
+
+ QWhatsThis::add(m_contents->openDataLink,
+ i18n("Shows data for table or query associated with this page setup."));
+ QToolTip::add(m_contents->openDataLink,
+ i18n("Shows data for table or query associated with this page setup."));
+ connect(m_contents->openDataLink, SIGNAL(leftClickedURL()), this, SLOT(slotOpenData()));
+
+ QWhatsThis::add(m_contents->saveSetupLink, i18n("Saves settings for this setup as default."));
+ connect(m_contents->saveSetupLink, SIGNAL(leftClickedURL()), this, SLOT(slotSaveSetup()));
+#if !KDE_IS_VERSION(3,5,1) && !defined(Q_WS_WIN)
+ //a fix for problems with focusable KUrlLabel on KDElibs<=3.5.0
+ m_contents->openDataLink->setFocusPolicy(NoFocus);
+ m_contents->saveSetupLink->setFocusPolicy(NoFocus);
+#endif
+
+ QWhatsThis::add(m_contents->addDateTimeCheckbox, i18n("Adds date and time to the header."));
+ QWhatsThis::add(m_contents->addPageNumbersCheckbox, i18n("Adds page numbers to the footer."));
+ QWhatsThis::add(m_contents->addTableBordersCheckbox, i18n("Adds table borders."));
+
+#ifdef KEXI_NO_UNFINISHED
+ m_contents->addDateTimeCheckbox->hide();
+ m_contents->addPageNumbersCheckbox->hide();
+#endif
+
+ updatePageLayoutAndUnitInfo();
+ QWhatsThis::add(m_contents->changePageSizeAndMarginsButton,
+ i18n("Changes page size and margins."));
+ connect(m_contents->changePageSizeAndMarginsButton, SIGNAL(clicked()),
+ this, SLOT(slotChangePageSizeAndMargins()));
+
+ connect(m_contents->addPageNumbersCheckbox, SIGNAL(toggled(bool)),
+ this, SLOT(slotAddPageNumbersCheckboxToggled(bool)));
+ connect(m_contents->addDateTimeCheckbox, SIGNAL(toggled(bool)),
+ this, SLOT(slotAddDateTimeCheckboxToggled(bool)));
+ connect(m_contents->addTableBordersCheckbox, SIGNAL(toggled(bool)),
+ this, SLOT(slotAddTableBordersCheckboxToggled(bool)));
+
+ if (!ok) {
+ // no data!
+ setEnabled(false);
+ }
+
+ m_contents->addPageNumbersCheckbox->setChecked( m_settings.addPageNumbers );
+ m_contents->addDateTimeCheckbox->setChecked( m_settings.addDateAndTime );
+ m_contents->addTableBordersCheckbox->setChecked( m_settings.addTableBorders );
+ setDirty(false);
+
+// m_engine = new KexiSimplePrintingEngine(m_settings, this);
+
+ //clear it back to false after widgets initialization
+ m_printPreviewNeedsReloading = false;
+
+/* if (printPreview)
+ QTimer::singleShot(50, this, SLOT(printPreview()));
+ else if (print)
+ QTimer::singleShot(50, this, SLOT(print()));*/
+ connect(this, SIGNAL(printItemRequested(KexiPart::Item*,const KexiSimplePrintingSettings&,
+ const QString&)),
+ m_mainWin, SLOT(printItem(KexiPart::Item*,const KexiSimplePrintingSettings&,
+ const QString&)));
+ connect(this, SIGNAL(printPreviewForItemRequested(KexiPart::Item*,
+ const KexiSimplePrintingSettings&,const QString&,bool)),
+ m_mainWin, SLOT(printPreviewForItem(KexiPart::Item*,
+ const KexiSimplePrintingSettings&,const QString&,bool)));
+}
+
+KexiSimplePrintingPageSetup::~KexiSimplePrintingPageSetup()
+{
+}
+
+void KexiSimplePrintingPageSetup::slotSaveSetup()
+{
+ m_settings.save();
+ setDirty(false);
+}
+
+void KexiSimplePrintingPageSetup::updatePageLayoutAndUnitInfo()
+{
+ QString s;
+ if (m_settings.pageLayout.format == PG_CUSTOM) {
+ s += QString(" (%1 %2 x %3 %4)")
+ .arg(m_settings.pageLayout.ptWidth).arg(KoUnit::unitName(m_unit))
+ .arg(m_settings.pageLayout.ptHeight).arg(KoUnit::unitName(m_unit));
+ }
+ else
+ s += KoPageFormat::name(m_settings.pageLayout.format);
+ s += QString(", ")
+ + (m_settings.pageLayout.orientation == PG_PORTRAIT ? i18n("Portrait") : i18n("Landscape"))
+ + ", " + i18n("margins:")
+ + " " + KoUnit::toUserStringValue(m_settings.pageLayout.ptLeft, m_unit)
+ + "/" + KoUnit::toUserStringValue(m_settings.pageLayout.ptRight, m_unit)
+ + "/" + KoUnit::toUserStringValue(m_settings.pageLayout.ptTop, m_unit)
+ + "/" + KoUnit::toUserStringValue(m_settings.pageLayout.ptBottom, m_unit)
+ + " " + KoUnit::unitName(m_unit);
+ m_contents->pageSizeAndMarginsLabel->setText( s );
+}
+
+/*void KexiSimplePrintingPageSetup::setupPrintingCommand()
+{
+ if (!m_command) {
+ m_command = new KexiSimplePrintingCommand(
+ m_mainWin, m_item->identifier(), m_settings, false/!owned/, this);
+ }
+}*/
+
+void KexiSimplePrintingPageSetup::print()
+{
+// setupPrintingCommand();
+// m_command->print(m_contents->headerTitleLineEdit->text());
+ emit printItemRequested(m_item, m_settings, m_contents->headerTitleLineEdit->text());
+}
+
+void KexiSimplePrintingPageSetup::printPreview()
+{
+// setupPrintingCommand();
+// m_command->showPrintPreview(m_contents->headerTitleLineEdit->text());
+ emit printPreviewForItemRequested(m_item, m_settings,
+ m_contents->headerTitleLineEdit->text(), m_printPreviewNeedsReloading);
+ m_printPreviewNeedsReloading = false;
+}
+
+void KexiSimplePrintingPageSetup::slotOpenData()
+{
+ bool openingCancelled;
+ m_mainWin->openObject(m_item, Kexi::DataViewMode, openingCancelled);
+}
+
+void KexiSimplePrintingPageSetup::slotTitleTextChanged(const QString&)
+{
+ if (m_contents->headerTitleLineEdit->isModified()) {
+ m_printPreviewNeedsReloading = true;
+// if (m_command)
+// m_command->setPrintPreviewNeedsReloading();
+ }
+
+ m_contents->headerTitleLineEdit->clearModified();
+}
+
+void KexiSimplePrintingPageSetup::slotChangeTitleFont()
+{
+ if (QDialog::Accepted != KFontDialog::getFont(m_settings.pageTitleFont, false, this))
+ return;
+ m_contents->headerTitleLineEdit->setFont( m_settings.pageTitleFont );
+ setDirty(true);
+}
+
+void KexiSimplePrintingPageSetup::slotChangePageSizeAndMargins()
+{
+ KoHeadFoot headfoot; //dummy
+
+ if (int(QDialog::Accepted) != KoPageLayoutDia::pageLayout(
+ m_settings.pageLayout, headfoot, FORMAT_AND_BORDERS | DISABLE_UNIT, m_unit, this ))
+ return;
+
+ //update
+ updatePageLayoutAndUnitInfo();
+ setDirty(true);
+}
+
+void KexiSimplePrintingPageSetup::setDirty(bool set)
+{
+ m_contents->saveSetupLink->setEnabled(set);
+// if (m_command)
+// m_command->setPrintPreviewNeedsReloading();
+ if (set)
+ m_printPreviewNeedsReloading = true;
+}
+
+void KexiSimplePrintingPageSetup::slotAddPageNumbersCheckboxToggled(bool set)
+{
+ m_settings.addPageNumbers = set;
+ setDirty(true);
+}
+
+void KexiSimplePrintingPageSetup::slotAddDateTimeCheckboxToggled(bool set)
+{
+ m_settings.addDateAndTime = set;
+ setDirty(true);
+}
+
+void KexiSimplePrintingPageSetup::slotAddTableBordersCheckboxToggled(bool set)
+{
+ m_settings.addTableBorders = set;
+ setDirty(true);
+}
+
+#include "kexisimpleprintingpagesetup.moc"
diff --git a/kexi/main/printing/kexisimpleprintingpagesetup.h b/kexi/main/printing/kexisimpleprintingpagesetup.h
new file mode 100644
index 00000000..e4e99bd5
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingpagesetup.h
@@ -0,0 +1,117 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KEXISIMPLEPRINTINGPAGESETUP_H
+#define KEXISIMPLEPRINTINGPAGESETUP_H
+
+#include "kexisimpleprintingengine.h"
+#include <kexiviewbase.h>
+
+class KexiSimplePrintingPageSetupBase;
+class KoPageLayoutSize;
+class KexiSimplePrintPreviewWindow;
+
+/*! @short A command for simple printing and print preview.
+ This class is instantiated in KexiMainWindowImpl so there's:
+ - a single print preview window per part item regardless of a way how user invoked
+ the 'print preview' command (using 'File->Print Preview' command or 'Print Preview' button
+ of the 'Page Setup' dialog)
+ - a single printing engine per part item regardless of a way how user started
+ (using 'File->Print' command or 'Print' button of the 'Page Setup' dialog)
+*/
+class KexiSimplePrintingCommand : public QObject
+{
+ Q_OBJECT
+
+ public:
+ KexiSimplePrintingCommand(KexiMainWindow* mainWin, int objectId,
+ QObject* parent = 0);
+ ~KexiSimplePrintingCommand();
+
+ public slots:
+ bool print(const KexiSimplePrintingSettings& settings,
+ const QString& aTitleText = QString::null);
+ bool print(const QString& aTitleText = QString::null);
+ bool showPrintPreview(const KexiSimplePrintingSettings& settings,
+ const QString& aTitleText = QString::null, bool reload = false);
+// void setPrintPreviewNeedsReloading();
+
+ signals:
+ //! connected to Kexi Main Window
+ void showPageSetupRequested(KexiPart::Item* item);
+
+ protected slots:
+ void slotShowPageSetupRequested();
+
+ protected:
+ KexiSimplePrintingEngine* m_previewEngine;
+ KexiMainWindow* m_mainWin;
+ int m_objectId;
+ KexiSimplePrintingSettings m_settings;
+ KexiSimplePrintPreviewWindow *m_previewWindow;
+ bool m_printPreviewNeedsReloading : 1;
+};
+
+//! @short A window for displaying settings for simple printing.
+class KexiSimplePrintingPageSetup : public KexiViewBase
+{
+ Q_OBJECT
+
+ public:
+ KexiSimplePrintingPageSetup( KexiMainWindow *mainWin, QWidget *parent, QMap<QString,QString>* args );
+ ~KexiSimplePrintingPageSetup();
+
+ public slots:
+ void print();
+ void printPreview();
+
+ signals:
+ void printItemRequested(KexiPart::Item* item,
+ const KexiSimplePrintingSettings& settings, const QString& titleText);
+ void printPreviewForItemRequested(KexiPart::Item* item,
+ const KexiSimplePrintingSettings& settings, const QString& titleText, bool reload);
+
+ protected slots:
+ void slotOpenData();
+ void slotSaveSetup();
+ void slotChangeTitleFont();
+ void slotChangePageSizeAndMargins();
+ void slotAddPageNumbersCheckboxToggled(bool set);
+ void slotAddDateTimeCheckboxToggled(bool set);
+ void slotAddTableBordersCheckboxToggled(bool set);
+ void slotTitleTextChanged(const QString&);
+
+ protected:
+ void setupPrintingCommand();
+ void updatePageLayoutAndUnitInfo();
+ void setDirty(bool set);
+
+ KexiSimplePrintingSettings m_settings;
+// KexiSimplePrintingEngine *m_engine;
+ KoUnit::Unit m_unit;
+ KexiSimplePrintingPageSetupBase *m_contents;
+ KoPageLayoutSize *m_pageLayoutWidget;
+ KexiPart::Item *m_item;
+// KexiSimplePrintingCommand *m_command;
+ QString m_origCaptionLabelText;
+ bool m_printPreviewNeedsReloading : 1;
+
+};
+
+#endif
diff --git a/kexi/main/printing/kexisimpleprintingpagesetupbase.ui b/kexi/main/printing/kexisimpleprintingpagesetupbase.ui
new file mode 100644
index 00000000..13c29ab0
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingpagesetupbase.ui
@@ -0,0 +1,447 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KexiSimplePrintingPageSetupBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiSimplePrintingPageSetupBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>338</width>
+ <height>451</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>.</string>
+ </property>
+ <property name="focusPolicy">
+ <enum>WheelFocus</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="6">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>iconLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>captionLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;h2&gt;Page Setup for Printing "%1" Table Data&lt;/h2&gt;</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>headerTitleLineEdit</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KLineEdit" row="5" column="0" rowspan="1" colspan="5">
+ <property name="name">
+ <cstring>headerTitleLineEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>2</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="5" column="5">
+ <property name="name">
+ <cstring>headerTitleFontButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Set Font...</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0" rowspan="1" colspan="5">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Page title:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignBottom</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>headerTitleLineEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="6">
+ <property name="name">
+ <cstring>layout19</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>printButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>printPreviewButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>230</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox" row="8" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>addPageNumbersCheckbox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add page numbers</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox" row="7" column="0" rowspan="1" colspan="5">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Page Size &amp;&amp; Margins</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>pageSizeAndMarginsLabel</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="KPushButton" row="7" column="5">
+ <property name="name">
+ <cstring>changePageSizeAndMarginsButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Change...</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="12" column="0" rowspan="1" colspan="6">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>spacer23</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>80</width>
+ <height>6</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLLabel" row="2" column="0">
+ <property name="name">
+ <cstring>saveSetupLink</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>WheelFocus</enum>
+ </property>
+ <property name="margin">
+ <number>3</number>
+ </property>
+ <property name="text">
+ <string>Save This Setup as Default</string>
+ </property>
+ <property name="indent">
+ <number>6</number>
+ </property>
+ <property name="url" stdset="0">
+ <string></string>
+ </property>
+ <property name="tipText">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KURLLabel" row="1" column="0">
+ <property name="name">
+ <cstring>openDataLink</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>WheelFocus</enum>
+ </property>
+ <property name="margin">
+ <number>3</number>
+ </property>
+ <property name="text">
+ <string>Open This Table</string>
+ </property>
+ <property name="indent">
+ <number>6</number>
+ </property>
+ <property name="url" stdset="0">
+ <string></string>
+ </property>
+ <property name="tipText">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>Related actions:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox" row="9" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>addDateTimeCheckbox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add date and time</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="10" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>addTableBordersCheckbox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add table borders</string>
+ </property>
+ </widget>
+ <spacer row="13" column="4">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer15</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="6" column="0">
+ <property name="name">
+ <cstring>spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="11" column="2">
+ <property name="name">
+ <cstring>spacer14</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>4</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>printButton</tabstop>
+ <tabstop>printPreviewButton</tabstop>
+ <tabstop>headerTitleLineEdit</tabstop>
+ <tabstop>headerTitleFontButton</tabstop>
+ <tabstop>changePageSizeAndMarginsButton</tabstop>
+ <tabstop>addPageNumbersCheckbox</tabstop>
+ <tabstop>addDateTimeCheckbox</tabstop>
+ <tabstop>addTableBordersCheckbox</tabstop>
+ <tabstop>openDataLink</tabstop>
+ <tabstop>saveSetupLink</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kurllabel.h</includehint>
+ <includehint>kurllabel.h</includehint>
+</includehints>
+</UI>
diff --git a/kexi/main/printing/kexisimpleprintingpart.cpp b/kexi/main/printing/kexisimpleprintingpart.cpp
new file mode 100644
index 00000000..765f6db2
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingpart.cpp
@@ -0,0 +1,63 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "kexisimpleprintingpart.h"
+#include "kexisimpleprintingpagesetup.h"
+
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <keximainwindow.h>
+#include <kexidialogbase.h>
+#include <kexiproject.h>
+#include <kexipartinfo.h>
+
+KexiSimplePrintingPart::KexiSimplePrintingPart()
+ : KexiPart::StaticPart("kexi/simpleprinting", "fileprint", i18n("Printing"))
+{
+ // REGISTERED ID:
+//?? m_registeredPartID = (int)KexiPart::QueryObjectType;
+
+/* m_names["instanceName"]
+ = i18n("Translate this word using only lowercase alphanumeric characters (a..z, 0..9). "
+ "Use '_' character instead of spaces. First character should be a..z character. "
+ "If you cannot use latin characters in your language, use english word.",
+ "query");*/
+ m_names["instanceCaption"] = i18n("Printing");
+ m_supportedViewModes = Kexi::DesignViewMode;
+ m_supportedUserViewModes = Kexi::DesignViewMode;
+}
+
+KexiSimplePrintingPart::~KexiSimplePrintingPart()
+{
+}
+
+KexiViewBase* KexiSimplePrintingPart::createView(QWidget *parent, KexiDialogBase* dialog,
+ KexiPart::Item &item, int viewMode, QMap<QString,QString>* args)
+{
+ Q_UNUSED( item );
+ if (viewMode == Kexi::DesignViewMode) {
+ KexiSimplePrintingPageSetup *w = new KexiSimplePrintingPageSetup( dialog->mainWin(), parent, args );
+ return w;
+ }
+
+ return 0;
+}
+
+#include "kexisimpleprintingpart.moc"
diff --git a/kexi/main/printing/kexisimpleprintingpart.h b/kexi/main/printing/kexisimpleprintingpart.h
new file mode 100644
index 00000000..1d2df3be
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintingpart.h
@@ -0,0 +1,51 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXISIMPLEPRINTINGPART_H
+#define KEXISIMPLEPRINTINGPART_H
+
+#include <kexidialogbase.h>
+#include <kexistaticpart.h>
+#include <kexipartitem.h>
+
+class KexiMainWin;
+namespace KexiDB
+{
+ class QuerySchema;
+ class Connection;
+}
+
+class KexiProject;
+
+//! @short Internal Kexi Simple Printing Plugin.
+class KexiSimplePrintingPart : public KexiPart::StaticPart
+{
+ Q_OBJECT
+
+ public:
+ KexiSimplePrintingPart();
+ virtual ~KexiSimplePrintingPart();
+
+ protected:
+ virtual KexiViewBase* createView(QWidget *parent, KexiDialogBase* dialog,
+ KexiPart::Item &item, int viewMode, QMap<QString,QString>* staticObjectArgs);
+};
+
+#endif
+
diff --git a/kexi/main/printing/kexisimpleprintpreviewwindow.cpp b/kexi/main/printing/kexisimpleprintpreviewwindow.cpp
new file mode 100644
index 00000000..4ba487d9
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintpreviewwindow.cpp
@@ -0,0 +1,381 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "kexisimpleprintpreviewwindow.h"
+#include "kexisimpleprintingengine.h"
+#include "kexisimpleprintpreviewwindow_p.h"
+#include <kexi_version.h>
+
+#include <qlayout.h>
+#include <qaccel.h>
+#include <qtimer.h>
+#include <qlabel.h>
+
+#include <kdialogbase.h>
+#include <ktoolbarbutton.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kpushbutton.h>
+#include <kapplication.h>
+
+KexiSimplePrintPreviewView::KexiSimplePrintPreviewView(
+ QWidget *parent, KexiSimplePrintPreviewWindow *window)
+ : QWidget(parent, "KexiSimplePrintPreviewView", WStaticContents)//|WNoAutoErase)
+ , m_window(window)
+{
+ enablePainting = false;
+// resize(300,400);
+// resizeContents(200, 400);
+}
+
+void KexiSimplePrintPreviewView::paintEvent( QPaintEvent *pe )
+{
+ Q_UNUSED(pe);
+ if (!enablePainting)
+ return;
+ QPixmap pm(size()); //dbl buffered
+ QPainter p;
+ p.begin(&pm, this);
+//! @todo only for screen!
+ p.fillRect(QRect(QPoint(0,0),pm.size()), QBrush(white));//pe->rect(), QBrush(white));
+ if (m_window->currentPage()>=0)
+ m_window->m_engine.paintPage(m_window->currentPage(), p);
+// emit m_window->paintingPageRequested(m_window->currentPage(), p);
+ p.end();
+ bitBlt(this, 0, 0, &pm);
+}
+
+//--------------------------
+
+#define KexiSimplePrintPreviewScrollView_MARGIN KDialogBase::marginHint()
+
+KexiSimplePrintPreviewScrollView::KexiSimplePrintPreviewScrollView(
+ KexiSimplePrintPreviewWindow *window)
+ : QScrollView(window, "scrollview", WStaticContents|WNoAutoErase)
+ , m_window(window)
+{
+// this->settings = settings;
+ widget = new KexiSimplePrintPreviewView(viewport(), m_window);
+
+/* int widthMM = KoPageFormat::width(
+ settings.pageLayout.format, settings.pageLayout.orientation);
+ int heightMM = KoPageFormat::height(
+ settings.pageLayout.format, settings.pageLayout.orientation);
+// int constantHeight = 400;
+// widget->resize(constantHeight * widthMM / heightMM, constantHeight ); //keep aspect
+*/
+ addChild(widget);
+}
+
+void KexiSimplePrintPreviewScrollView::resizeEvent( QResizeEvent *re )
+{
+ QScrollView::resizeEvent(re);
+// kdDebug() << re->size().width() << " " << re->size().height() << endl;
+// kdDebug() << contentsWidth() << " " << contentsHeight() << endl;
+// kdDebug() << widget->width() << " " << widget->height() << endl;
+ setUpdatesEnabled(false);
+ if (re->size().width() > (widget->width()+2*KexiSimplePrintPreviewScrollView_MARGIN)
+ || re->size().height() > (widget->height()+2*KexiSimplePrintPreviewScrollView_MARGIN))
+ {
+ resizeContents(
+ QMAX(re->size().width(), widget->width()+2*KexiSimplePrintPreviewScrollView_MARGIN),
+ QMAX(re->size().height(), widget->height()+2*KexiSimplePrintPreviewScrollView_MARGIN));
+ int vscrbarWidth = verticalScrollBar()->isVisible() ? verticalScrollBar()->width() : 0;
+ int newContentsWidth
+ = QMAX(re->size().width(), widget->width()+2*KexiSimplePrintPreviewScrollView_MARGIN);
+ int newContentsHeight
+ = QMAX(re->size().height(), widget->height()+2*KexiSimplePrintPreviewScrollView_MARGIN);
+ moveChild(widget, (newContentsWidth - vscrbarWidth - widget->width())/2,
+ (newContentsHeight - widget->height())/2);
+ resizeContents( newContentsWidth, newContentsHeight );
+ }
+ setUpdatesEnabled(true);
+}
+
+void KexiSimplePrintPreviewScrollView::setFullWidth()
+{
+ viewport()->setUpdatesEnabled(false);
+ double widthMM = KoPageFormat::width(
+ m_window->settings().pageLayout.format,
+ m_window->settings().pageLayout.orientation);
+ double heightMM = KoPageFormat::height(
+ m_window->settings().pageLayout.format, m_window->settings().pageLayout.orientation);
+// int constantWidth = m_window->width()- KexiSimplePrintPreviewScrollView_MARGIN*6;
+ double constantWidth = width()- KexiSimplePrintPreviewScrollView_MARGIN*6;
+ double heightForWidth = constantWidth * heightMM / widthMM;
+// heightForWidth = QMIN(kapp->desktop()->height()*4/5, heightForWidth);
+ kdDebug() << "1: " << heightForWidth << endl;
+#if 0 //todo we can use this if we want to fix the height to width of the page
+ heightForWidth = QMIN(height(), heightForWidth);
+ kdDebug() << "2: " << heightForWidth << endl;
+#endif
+ constantWidth = heightForWidth * widthMM / heightMM;
+ widget->resize((int)constantWidth, (int)heightForWidth); //keep aspect
+ resizeContents(int(widget->width() + 2*KexiSimplePrintPreviewScrollView_MARGIN),
+ int(widget->height() + 2*KexiSimplePrintPreviewScrollView_MARGIN));
+ moveChild(widget, (contentsWidth()-widget->width())/2,
+ (contentsHeight()-widget->height())/2);
+ viewport()->setUpdatesEnabled(true);
+ resize(size()+QSize(1,1)); //to update pos.
+ widget->enablePainting = true;
+ widget->repaint();
+}
+
+void KexiSimplePrintPreviewScrollView::setContentsPos(int x, int y)
+{
+// kdDebug() << "############" << x << " " << y << " " << contentsX()<< " " <<contentsY() << endl;
+ if (x<0 || y<0) //to avoid endless loop on Linux
+ return;
+ QScrollView::setContentsPos(x,y);
+}
+
+//------------------
+
+KexiSimplePrintPreviewWindow::KexiSimplePrintPreviewWindow(
+ KexiSimplePrintingEngine &engine, const QString& previewName,
+ QWidget *parent, WFlags f)
+ : QWidget(parent, "KexiSimplePrintPreviewWindow", f)
+ , m_engine(engine)
+ , m_settings(*m_engine.settings())
+ , m_pageNumber(-1)
+ , m_pagesCount(-1)
+{
+ setCaption(i18n("%1 - Print Preview - %2").arg(previewName).arg(KEXI_APP_NAME));
+ setIcon(DesktopIcon("filequickprint"));
+ QVBoxLayout *lyr = new QVBoxLayout(this, 6);
+
+ int id;
+ m_toolbar = new KToolBar(0, this);
+ m_toolbar->setLineWidth(0);
+ m_toolbar->setFrameStyle(QFrame::NoFrame);
+ m_toolbar->setIconText(KToolBar::IconTextRight);
+ lyr->addWidget(m_toolbar);
+
+ id = m_toolbar->insertWidget( -1, 0, new KPushButton(KStdGuiItem::print(), m_toolbar) );
+ m_toolbar->addConnection(id, SIGNAL(clicked()), this, SLOT(slotPrintClicked()));
+ static_cast<KPushButton*>(m_toolbar->getWidget(id))->setAccel(Qt::CTRL|Qt::Key_P);
+ m_toolbar->insertSeparator();
+
+ id = m_toolbar->insertWidget(-1, 0, new KPushButton(i18n("Page Set&up..."), m_toolbar));
+ m_toolbar->addConnection(id, SIGNAL(clicked()), this, SLOT(slotPageSetup()));
+ m_toolbar->insertSeparator();
+
+
+#ifndef KEXI_NO_UNFINISHED
+//! @todo unfinished
+ id = m_toolbar->insertWidget( -1, 0, new KPushButton(BarIconSet("viewmag+"), i18n("Zoom In"), m_toolbar));
+ m_toolbar->addConnection(id, SIGNAL(clicked()), this, SLOT(slotZoomInClicked()));
+ m_toolbar->insertSeparator();
+
+ id = m_toolbar->insertWidget( -1, 0, new KPushButton(BarIconSet("viewmag-"), i18n("Zoom Out"), m_toolbar));
+ m_toolbar->addConnection(id, SIGNAL(clicked()), this, SLOT(slotZoomOutClicked()));
+ m_toolbar->insertSeparator();
+#endif
+
+ id = m_toolbar->insertWidget(-1, 0, new KPushButton(KStdGuiItem::close(), m_toolbar));
+ m_toolbar->addConnection(id, SIGNAL(clicked()), this, SLOT(close()));
+ m_toolbar->alignItemRight(id);
+
+ m_scrollView = new KexiSimplePrintPreviewScrollView(this);
+ m_scrollView->setUpdatesEnabled(false);
+ m_view = m_scrollView->widget;
+ m_scrollView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ lyr->addWidget(m_scrollView);
+
+ QWidget* navToolbarWidget = new QWidget(this); //widget used to center the navigator toolbar
+ navToolbarWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ QHBoxLayout *navToolbarLyr = new QHBoxLayout(navToolbarWidget);
+ lyr->addWidget(navToolbarWidget);
+
+ m_navToolbar = new KToolBar(0, navToolbarWidget);
+ navToolbarLyr->addStretch(1);
+ navToolbarLyr->addWidget(m_navToolbar);
+ navToolbarLyr->addStretch(1);
+// m_navToolbar->setFullWidth(true);
+ m_navToolbar->setLineWidth(0);
+ m_navToolbar->setFrameStyle(QFrame::NoFrame);
+ m_navToolbar->setIconText(KToolBar::IconTextRight);
+
+ m_idFirst = m_navToolbar->insertWidget( -1, 0, new KPushButton(BarIconSet("start"), i18n("First Page"), m_navToolbar));
+ m_navToolbar->addConnection(m_idFirst, SIGNAL(clicked()), this, SLOT(slotFirstClicked()));
+ m_navToolbar->insertSeparator();
+
+ m_idPrevious = m_navToolbar->insertWidget( -1, 0, new KPushButton(BarIconSet("previous"), i18n("Previous Page"), m_navToolbar));
+ m_navToolbar->addConnection(m_idPrevious, SIGNAL(clicked()), this, SLOT(slotPreviousClicked()));
+ m_navToolbar->insertSeparator();
+
+ m_idPageNumberLabel = m_navToolbar->insertWidget( -1, 0, new QLabel(m_navToolbar));
+ m_navToolbar->insertSeparator();
+
+ m_idNext = m_navToolbar->insertWidget( -1, 0, new KPushButton(BarIconSet("next"), i18n("Next Page"), m_navToolbar));
+ m_navToolbar->addConnection(m_idNext, SIGNAL(clicked()), this, SLOT(slotNextClicked()));
+ m_navToolbar->insertSeparator();
+
+ m_idLast = m_navToolbar->insertWidget( -1, 0, new KPushButton(BarIconSet("finish"), i18n("Last Page"), m_navToolbar));
+ m_navToolbar->addConnection(m_idLast, SIGNAL(clicked()), this, SLOT(slotLastClicked()));
+ m_navToolbar->insertSeparator();
+
+ resize(width(), kapp->desktop()->height()*4/5);
+
+//! @todo progress bar...
+
+ QTimer::singleShot(50, this, SLOT(initLater()));
+}
+
+void KexiSimplePrintPreviewWindow::initLater()
+{
+ setFullWidth();
+ updatePagesCount();
+ goToPage(0);
+}
+
+KexiSimplePrintPreviewWindow::~KexiSimplePrintPreviewWindow()
+{
+}
+
+/*void KexiSimplePrintPreviewWindow::setPagesCount(int pagesCount)
+{
+ m_pagesCount = pagesCount;
+ goToPage(0);
+}*/
+
+void KexiSimplePrintPreviewWindow::slotPrintClicked()
+{
+ hide();
+ emit printRequested();
+ show();
+ raise();
+}
+
+void KexiSimplePrintPreviewWindow::slotPageSetup()
+{
+ lower();
+ emit pageSetupRequested();
+}
+
+void KexiSimplePrintPreviewWindow::slotZoomInClicked()
+{
+ //! @todo
+}
+
+void KexiSimplePrintPreviewWindow::slotZoomOutClicked()
+{
+ //! @todo
+}
+
+void KexiSimplePrintPreviewWindow::slotFirstClicked()
+{
+ goToPage(0);
+}
+
+void KexiSimplePrintPreviewWindow::slotPreviousClicked()
+{
+ goToPage(m_pageNumber-1);
+}
+
+void KexiSimplePrintPreviewWindow::slotNextClicked()
+{
+ goToPage(m_pageNumber+1);
+}
+
+void KexiSimplePrintPreviewWindow::slotLastClicked()
+{
+ goToPage(m_engine.pagesCount()-1);
+}
+
+void KexiSimplePrintPreviewWindow::goToPage(int pageNumber)
+{
+ if ((pageNumber==m_pageNumber && m_pagesCount == (int)m_engine.pagesCount())
+ || pageNumber < 0 || pageNumber > ((int)m_engine.pagesCount()-1))
+ return;
+ m_pageNumber = pageNumber;
+ m_pagesCount = m_engine.pagesCount();
+
+ m_view->repaint(); //this will automatically paint a new page
+
+ m_navToolbar->setItemEnabled(m_idNext, pageNumber < ((int)m_engine.pagesCount()-1));
+ m_navToolbar->setItemEnabled(m_idLast, pageNumber < ((int)m_engine.pagesCount()-1));
+ m_navToolbar->setItemEnabled(m_idPrevious, pageNumber > 0);
+ m_navToolbar->setItemEnabled(m_idFirst, pageNumber > 0);
+ static_cast<QLabel*>(m_navToolbar->getWidget(m_idPageNumberLabel))->setText(
+ i18n("Page (number) of (total)", "Page %1 of %2").arg(m_pageNumber+1).arg(m_engine.pagesCount()));
+}
+
+void KexiSimplePrintPreviewWindow::setFullWidth()
+{
+ m_scrollView->setFullWidth();
+}
+
+void KexiSimplePrintPreviewWindow::updatePagesCount()
+{
+ QPixmap pm(m_view->size()); //dbl buffered
+ QPainter p(m_view);
+ //p.begin(&pm, this);
+////! @todo only for screen!
+// p.fillRect(pe->rect(), QBrush(white));
+ m_engine.calculatePagesCount(p);
+ p.end();
+}
+
+bool KexiSimplePrintPreviewWindow::event( QEvent * e )
+{
+ QEvent::Type t = e->type();
+ if (t==QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ const int k = ke->key();
+ bool ok = true;
+ if (k==Qt::Key_Equal || k==Qt::Key_Plus)
+ slotZoomInClicked();
+ else if (k==Qt::Key_Minus)
+ slotZoomOutClicked();
+ else if (k==Qt::Key_Home)
+ slotFirstClicked();
+ else if (k==Qt::Key_End)
+ slotLastClicked();
+ else
+ ok = false;
+
+ if (ok) {
+ ke->accept();
+ return true;
+ }
+ }
+ else if (t==QEvent::AccelOverride) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(e);
+ const int k = ke->key();
+ bool ok = true;
+ if (k==Qt::Key_PageUp)
+ slotPreviousClicked();
+ else if (k==Qt::Key_PageDown)
+ slotNextClicked();
+ else
+ ok = false;
+
+ if (ok) {
+ ke->accept();
+ return true;
+ }
+ }
+ return QWidget::event(e);
+}
+
+
+#include "kexisimpleprintpreviewwindow.moc"
+#include "kexisimpleprintpreviewwindow_p.moc"
diff --git a/kexi/main/printing/kexisimpleprintpreviewwindow.h b/kexi/main/printing/kexisimpleprintpreviewwindow.h
new file mode 100644
index 00000000..c91fa2f2
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintpreviewwindow.h
@@ -0,0 +1,83 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXISIMPLEPRINTPREVIEWWINDOW_H
+#define KEXISIMPLEPRINTPREVIEWWINDOW_H
+
+#include <qpainter.h>
+#include <qscrollview.h>
+#include <ktoolbar.h>
+#include <KoPageLayoutDia.h>
+
+class KexiSimplePrintPreviewScrollView;
+class KexiSimplePrintPreviewView;
+class KexiSimplePrintingSettings;
+class KexiSimplePrintingEngine;
+
+//! @short A window for displaying print preview for simple printing.
+class KexiSimplePrintPreviewWindow : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ KexiSimplePrintPreviewWindow(KexiSimplePrintingEngine &engine,
+ const QString& previewName, QWidget *parent, WFlags f = 0);
+ ~KexiSimplePrintPreviewWindow();
+
+ int currentPage() const { return m_pageNumber; }
+
+ const KexiSimplePrintingSettings& settings() const { return m_settings; }
+
+ public slots:
+ void updatePagesCount();
+// void setPagesCount(int pagesCount);
+ void goToPage(int pageNumber);
+ void setFullWidth();
+
+ signals:
+ void printRequested();
+ void pageSetupRequested();
+
+ protected slots:
+ void slotPageSetup();
+ void slotPrintClicked();
+ void slotZoomInClicked();
+ void slotZoomOutClicked();
+ void slotFirstClicked();
+ void slotPreviousClicked();
+ void slotNextClicked();
+ void slotLastClicked();
+ void initLater();
+
+ protected:
+ virtual bool event( QEvent * e );
+
+ KexiSimplePrintingEngine &m_engine;
+ const KexiSimplePrintingSettings& m_settings;
+ KToolBar *m_toolbar, *m_navToolbar;
+ int m_pageNumber;
+ int m_pagesCount; //!< needed to know that pages could has been changed
+ int m_idFirst, m_idLast, m_idPrevious, m_idNext, m_idPageNumberLabel;
+ KexiSimplePrintPreviewScrollView *m_scrollView;
+ KexiSimplePrintPreviewView *m_view;
+
+ friend class KexiSimplePrintPreviewView;
+};
+
+#endif
diff --git a/kexi/main/printing/kexisimpleprintpreviewwindow_p.h b/kexi/main/printing/kexisimpleprintpreviewwindow_p.h
new file mode 100644
index 00000000..e7a3804d
--- /dev/null
+++ b/kexi/main/printing/kexisimpleprintpreviewwindow_p.h
@@ -0,0 +1,55 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXISIMPLEPRINTPREVIEWWINDOW_P_H
+#define KEXISIMPLEPRINTPREVIEWWINDOW_P_H
+
+#include <kexisimpleprintpreviewwindow.h>
+
+class KexiSimplePrintPreviewView : public QWidget
+{
+ public:
+ KexiSimplePrintPreviewView(QWidget *parent, KexiSimplePrintPreviewWindow *window);
+
+ virtual void paintEvent( QPaintEvent *pe );
+
+ bool enablePainting;
+ protected:
+ KexiSimplePrintPreviewWindow *m_window;
+};
+
+class KexiSimplePrintPreviewScrollView : public QScrollView
+{
+ Q_OBJECT
+
+ public:
+ KexiSimplePrintPreviewScrollView(KexiSimplePrintPreviewWindow *window);
+
+ KexiSimplePrintPreviewView *widget;
+
+ public slots:
+ void setFullWidth();
+ void setContentsPos(int x, int y);
+
+ protected:
+ virtual void resizeEvent( QResizeEvent *re );
+ KexiSimplePrintPreviewWindow *m_window;
+};
+
+#endif
diff --git a/kexi/main/startup/KexiConnSelector.cpp b/kexi/main/startup/KexiConnSelector.cpp
new file mode 100644
index 00000000..454f1e08
--- /dev/null
+++ b/kexi/main/startup/KexiConnSelector.cpp
@@ -0,0 +1,432 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003,2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiConnSelector.h"
+
+#include <kexidb/drivermanager.h>
+#include <kexidb/connectiondata.h>
+
+#include <kexi.h>
+#include "KexiConnSelectorBase.h"
+//#include "KexiOpenExistingFile.h"
+#include <widget/kexiprjtypeselector.h>
+#include <widget/kexidbconnectionwidget.h>
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kurlcombobox.h>
+#include <ktoolbar.h>
+#include <kpopupmenu.h>
+#include <ktoolbarbutton.h>
+#include <kactionclasses.h>
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qtooltip.h>
+#include <qtextedit.h>
+#include <qgroupbox.h>
+#include <qwidgetstack.h>
+#include <qbuttongroup.h>
+
+ConnectionDataLVItem::ConnectionDataLVItem(KexiDB::ConnectionData *data,
+ const KexiDB::Driver::Info& info, QListView *list)
+ : QListViewItem(list)
+ , m_data(data)
+{
+ update(info);
+}
+
+ConnectionDataLVItem::~ConnectionDataLVItem()
+{
+}
+
+void ConnectionDataLVItem::update(const KexiDB::Driver::Info& info)
+{
+ setText(0, m_data->caption+" ");
+ const QString &sfile = i18n("File");
+ QString drvname = info.caption.isEmpty() ? m_data->driverName : info.caption;
+ if (info.fileBased)
+ setText(1, sfile + " ("+drvname+") " );
+ else
+ setText(1, drvname+" " );
+ setText(2, (info.fileBased ? (QString("<")+sfile.lower()+">") : m_data->serverInfoString(true))+" " );
+}
+
+/*================================================================*/
+
+//! @internal
+class KexiConnSelectorWidgetPrivate
+{
+public:
+ KexiConnSelectorWidgetPrivate()
+ : conn_sel_shown(false)
+ , file_sel_shown(false)
+ , confirmOverwrites(true)
+ {
+ }
+
+ QWidget* openExistingWidget;
+ KexiPrjTypeSelector* prjTypeSelector;
+ QString startDirOrVariable;
+ QWidgetStack *stack;
+ QGuardedPtr<KexiDBConnectionSet> conn_set;
+ KexiDB::DriverManager manager;
+ bool conn_sel_shown;//! helper
+ bool file_sel_shown;
+ bool confirmOverwrites;
+};
+
+/*================================================================*/
+
+KexiConnSelectorWidget::KexiConnSelectorWidget( KexiDBConnectionSet& conn_set,
+ const QString& startDirOrVariable, QWidget* parent, const char* name )
+ : QWidget( parent, name )
+ ,d(new KexiConnSelectorWidgetPrivate())
+{
+ d->conn_set = &conn_set;
+ d->startDirOrVariable = startDirOrVariable;
+ QString none, iconname = KMimeType::mimeType( KexiDB::Driver::defaultFileBasedDriverMimeType() )->icon(none,0);
+ const QPixmap &icon = KGlobal::iconLoader()->loadIcon( iconname, KIcon::Desktop );
+ setIcon( icon );
+
+ QVBoxLayout* globalLyr = new QVBoxLayout( this );
+
+ //create header with radio buttons
+ d->openExistingWidget = new QWidget(this, "openExistingWidget");
+ QVBoxLayout* openExistingWidgetLyr = new QVBoxLayout( d->openExistingWidget );
+// QLabel* lbl = new QLabel(i18n("<b>Select existing Kexi project to open:</b>"), openExistingWidget);
+// openExistingWidgetLyr->addWidget( lbl );
+ d->prjTypeSelector = new KexiPrjTypeSelector( d->openExistingWidget );
+ connect(d->prjTypeSelector->buttonGroup,SIGNAL(clicked(int)),this,SLOT(slotPrjTypeSelected(int)));
+ openExistingWidgetLyr->addWidget( d->prjTypeSelector );
+ openExistingWidgetLyr->addSpacing( KDialogBase::spacingHint() );
+ QFrame* line = new QFrame( d->openExistingWidget, "line" );
+ line->setFrameShape( QFrame::HLine );
+ line->setFrameShadow( QFrame::Sunken );
+ openExistingWidgetLyr->addWidget( line );
+ globalLyr->addWidget(d->openExistingWidget);
+
+ d->stack = new QWidgetStack(this, "stack");
+ globalLyr->addWidget(d->stack);
+
+// m_file = new KexiOpenExistingFile( this, "KexiOpenExistingFile");
+// m_file->btn_advanced->setIconSet( SmallIconSet("1downarrow") );
+ m_fileDlg = 0;
+
+// addWidget(m_file);
+// connect(m_file->btn_advanced,SIGNAL(clicked()),this,SLOT(showAdvancedConn()));
+
+ m_remote = new KexiConnSelectorBase(d->stack, "conn_sel");
+ m_remote->icon->setPixmap( DesktopIcon("network") );
+ m_remote->icon->setFixedSize( m_remote->icon->pixmap()->size() );
+// m_remote->btn_back->setIconSet( SmallIconSet("1uparrow") );
+ connect(m_remote->btn_add, SIGNAL(clicked()), this, SLOT(slotRemoteAddBtnClicked()));
+ connect(m_remote->btn_edit, SIGNAL(clicked()), this, SLOT(slotRemoteEditBtnClicked()));
+ connect(m_remote->btn_remove, SIGNAL(clicked()), this, SLOT(slotRemoteRemoveBtnClicked()));
+ QToolTip::add(m_remote->btn_add, i18n("Add a new database connection"));
+ QToolTip::add(m_remote->btn_edit, i18n("Edit selected database connection"));
+ QToolTip::add(m_remote->btn_remove, i18n("Remove selected database connections"));
+ d->stack->addWidget(m_remote);
+ if (m_remote->layout())
+ m_remote->layout()->setMargin(0);
+// connect(m_remote->btn_back,SIGNAL(clicked()),this,SLOT(showSimpleConn()));
+ connect(m_remote->list,SIGNAL(doubleClicked(QListViewItem*)),
+ this,SLOT(slotConnectionItemExecuted(QListViewItem*)));
+ connect(m_remote->list,SIGNAL(returnPressed(QListViewItem*)),
+ this,SLOT(slotConnectionItemExecuted(QListViewItem*)));
+ connect(m_remote->list,SIGNAL(selectionChanged()),
+ this,SLOT(slotConnectionSelectionChanged()));
+}
+
+KexiConnSelectorWidget::~KexiConnSelectorWidget()
+{
+ delete d;
+}
+
+/*void KexiConnSelectorWidget::disconnectShowSimpleConnButton()
+{
+ m_remote->btn_back->disconnect(this,SLOT(showSimpleConn()));
+}*/
+
+void KexiConnSelectorWidget::showAdvancedConn()
+{
+ slotPrjTypeSelected(2);
+ d->prjTypeSelector->buttonGroup->setButton(2);
+}
+
+//void KexiConnSelectorWidget::showAdvancedConn()
+void KexiConnSelectorWidget::slotPrjTypeSelected(int id)
+{
+ if (id==1) {//file-based prj type
+ showSimpleConn();
+ }
+ else if (id==2) {//server-based prj type
+ if (!d->conn_sel_shown) {
+ d->conn_sel_shown=true;
+
+ //show connections (on demand):
+ for (KexiDB::ConnectionData::ListIterator it(d->conn_set->list()); it.current(); ++it) {
+ addConnectionData( it.current() );
+ // else {
+ //this error should be more verbose:
+ // kdWarning() << "KexiConnSelector::KexiConnSelector(): no driver found for '" << it.current()->driverName << "'!" << endl;
+ // }
+ }
+ if (m_remote->list->firstChild()) {
+ m_remote->list->setSelected(m_remote->list->firstChild(),true);
+ }
+ m_remote->descriptionEdit->setPaletteBackgroundColor(palette().active().background());
+ m_remote->descGroupBox->layout()->setMargin(2);
+ m_remote->list->setFocus();
+ slotConnectionSelectionChanged();
+ }
+ d->stack->raiseWidget(m_remote);
+ }
+}
+
+ConnectionDataLVItem* KexiConnSelectorWidget::addConnectionData( KexiDB::ConnectionData* data )
+{
+ const KexiDB::Driver::Info info( d->manager.driverInfo(data->driverName) );
+// if (!info.name.isEmpty()) {
+ return new ConnectionDataLVItem(data, info, m_remote->list);
+// }
+}
+
+void KexiConnSelectorWidget::showSimpleConn()
+{
+ d->prjTypeSelector->buttonGroup->setButton(1);
+ if (!d->file_sel_shown) {
+ d->file_sel_shown=true;
+ m_fileDlg = new KexiStartupFileDialog( d->startDirOrVariable, KexiStartupFileDialog::Opening,
+ d->stack, "openExistingFileDlg");
+ m_fileDlg->setConfirmOverwrites( d->confirmOverwrites );
+// static_cast<QVBoxLayout*>(m_file->layout())->insertWidget( 2, m_fileDlg );
+ d->stack->addWidget(m_fileDlg);
+
+ for (QWidget *w = parentWidget(true);w;w=w->parentWidget(true)) {
+ if (w->isDialog()) {
+//#ifndef Q_WS_WIN
+ connect(m_fileDlg,SIGNAL(rejected()),static_cast<QDialog*>(w),SLOT(reject()));
+//#endif
+// connect(m_fileDlg,SIGNAL(cancelled()),static_cast<QDialog*>(w),SLOT(reject()));
+ break;
+ }
+ }
+ }
+ d->stack->raiseWidget(m_fileDlg);
+}
+
+int KexiConnSelectorWidget::selectedConnectionType() const
+{
+ return (d->stack->visibleWidget()==m_fileDlg) ? FileBased : ServerBased;
+}
+
+/*ConnectionDataLVItem* KexiConnSelectorWidget::selectedConnectionDataItem() const
+{
+ if (selectedConnectionType()!=KexiConnSelectorWidget::ServerBased)
+ return 0;
+ ConnectionDataLVItem *item = 0; // = static_cast<ConnectionDataLVItem*>(m_remote->list->selectedItem());
+ for (QListViewItemIterator it(m_remote->list); it.current(); ++it) {
+ if (it.current()->isSelected()) {
+ if (item)
+ return 0; //multiple
+ item = static_cast<ConnectionDataLVItem*>(it.current());
+ }
+ }
+ return item;
+}*/
+
+KexiDB::ConnectionData* KexiConnSelectorWidget::selectedConnectionData() const
+{
+ ConnectionDataLVItem *item = static_cast<ConnectionDataLVItem*>(m_remote->list->selectedItem()); //ConnectionDataItem();
+ if (!item)
+ return 0;
+ return item->data();
+}
+
+QString KexiConnSelectorWidget::selectedFileName()
+{
+ if (selectedConnectionType()!=KexiConnSelectorWidget::FileBased)
+ return QString::null;
+ return m_fileDlg->currentFileName();
+}
+
+void KexiConnSelectorWidget::setSelectedFileName(const QString& fileName)
+{
+ if (selectedConnectionType()!=KexiConnSelectorWidget::FileBased)
+ return;
+ return m_fileDlg->setSelection(fileName);
+}
+
+void KexiConnSelectorWidget::slotConnectionItemExecuted(QListViewItem *item)
+{
+ emit connectionItemExecuted(static_cast<ConnectionDataLVItem*>(item));
+}
+
+void KexiConnSelectorWidget::slotConnectionSelectionChanged()
+{
+ ConnectionDataLVItem* item = static_cast<ConnectionDataLVItem*>(m_remote->list->selectedItem());
+ //update buttons availability
+/* ConnectionDataLVItem *singleItem = 0;
+ bool multi = false;
+ for (QListViewItemIterator it(m_remote->list); it.current(); ++it) {
+ if (it.current()->isSelected()) {
+ if (singleItem) {
+ singleItem = 0;
+ multi = true;
+ break;
+ }
+ else
+ singleItem = static_cast<ConnectionDataLVItem*>(it.current());
+ }
+ }*/
+ m_remote->btn_edit->setEnabled(item);
+ m_remote->btn_remove->setEnabled(item);
+ m_remote->descriptionEdit->setText(item ? item->data()->description : QString::null);
+ emit connectionItemHighlighted(item);
+}
+
+QListView* KexiConnSelectorWidget::connectionsList() const
+{
+ return m_remote->list;
+}
+
+void KexiConnSelectorWidget::setFocus()
+{
+ QWidget::setFocus();
+ if (d->stack->visibleWidget()==m_fileDlg)
+ m_fileDlg->setFocus(); //m_fileDlg->locationWidget()->setFocus();
+ else
+ m_remote->list->setFocus();
+}
+
+void KexiConnSelectorWidget::hideHelpers()
+{
+ d->openExistingWidget->hide();
+
+/* m_file->lbl->hide();
+ m_file->line->hide();
+ m_file->spacer->hide();
+ m_file->label->hide();
+ m_remote->label->hide();
+ m_remote->label_back->hide();
+ m_remote->btn_back->hide();
+ m_remote->icon->hide();*/
+}
+
+void KexiConnSelectorWidget::setConfirmOverwrites(bool set)
+{
+ d->confirmOverwrites = set;
+ if (m_fileDlg)
+ m_fileDlg->setConfirmOverwrites( d->confirmOverwrites );
+}
+
+bool KexiConnSelectorWidget::confirmOverwrites() const
+{
+ return d->confirmOverwrites;
+}
+
+/*static QString msgUnfinished() {
+ return i18n("To define or change a connection, use command line options or click on .kexis file. "
+ "You can find example .kexis file at <a href=\"%1\">here</a>.").arg("") //temporary, please do not change for 0.8!
+ + "\nhttp://www.kexi-project.org/resources/testdb.kexis"; */
+// .arg("http://websvn.kde.org/*checkout*/branches/kexi/0.9/koffice/kexi/tests/startup/testdb.kexis");
+//}
+
+void KexiConnSelectorWidget::slotRemoteAddBtnClicked()
+{
+ KexiDB::ConnectionData data;
+ KexiDBConnectionDialog dlg(data, QString::null,
+ KGuiItem(i18n("&Add"), "button_ok", i18n("Add database connection")) );
+ dlg.setCaption(i18n("Add New Database Connection"));
+ if (QDialog::Accepted!=dlg.exec())
+ return;
+
+ //store this conn. data
+ KexiDB::ConnectionData *newData = new KexiDB::ConnectionData(*dlg.currentProjectData().connectionData());
+ if (!d->conn_set->addConnectionData(newData)) {
+ //! @todo msg?
+ delete newData;
+ return;
+ }
+
+ ConnectionDataLVItem* item = addConnectionData(newData);
+// m_remote->list->clearSelection();
+ m_remote->list->setSelected(item, true);
+ slotConnectionSelectionChanged();
+}
+
+void KexiConnSelectorWidget::slotRemoteEditBtnClicked()
+{
+ ConnectionDataLVItem* item = static_cast<ConnectionDataLVItem*>(m_remote->list->selectedItem());
+ if (!item)
+ return;
+ KexiDBConnectionDialog dlg(*item->data(), QString::null,
+ KGuiItem(i18n("&Save"), "filesave", i18n("Save changes made to this database connection")) );
+ dlg.setCaption(i18n("Edit Database Connection"));
+ if (QDialog::Accepted!=dlg.exec())
+ return;
+
+ KexiDB::ConnectionData *newData = new KexiDB::ConnectionData( *dlg.currentProjectData().connectionData() );
+ if (!d->conn_set->saveConnectionData(item->data(), newData)) {
+ //! @todo msg?
+ delete newData;
+ return;
+ }
+ const KexiDB::Driver::Info info( d->manager.driverInfo(item->data()->driverName) );
+ item->update(info);
+ slotConnectionSelectionChanged(); //to update descr. edit
+}
+
+void KexiConnSelectorWidget::slotRemoteRemoveBtnClicked()
+{
+ ConnectionDataLVItem* item = static_cast<ConnectionDataLVItem*>(m_remote->list->selectedItem());
+ if (!item)
+ return;
+ if (KMessageBox::Continue!=KMessageBox::warningContinueCancel(0,
+ i18n("Do you want to remove database connection \"%1\" from the list of available connections?")
+ .arg(item->data()->serverInfoString(true)), QString::null, KStdGuiItem::del(), QString::null,
+ KMessageBox::Notify|KMessageBox::Dangerous))
+ return;
+
+ QListViewItem* nextItem = item->itemBelow();
+ if (!nextItem)
+ nextItem = item->itemAbove();
+ if (!d->conn_set->removeConnectionData(item->data()))
+ return;
+
+ m_remote->list->removeItem(item);
+ if (nextItem)
+ m_remote->list->setSelected(nextItem, true);
+ slotConnectionSelectionChanged();
+}
+
+void KexiConnSelectorWidget::hideConnectonIcon()
+{
+ m_remote->icon->setFixedWidth(0);
+ m_remote->icon->setPixmap(QPixmap());
+}
+
+#include "KexiConnSelector.moc"
diff --git a/kexi/main/startup/KexiConnSelector.h b/kexi/main/startup/KexiConnSelector.h
new file mode 100644
index 00000000..a52dd8ae
--- /dev/null
+++ b/kexi/main/startup/KexiConnSelector.h
@@ -0,0 +1,142 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003,2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KEXICONNSELECTOR_H
+#define KEXICONNSELECTOR_H
+
+#include <kexidbconnectionset.h>
+#include <kexidb/driver.h>
+#include "KexiStartupFileDialog.h"
+
+#include <kdialogbase.h>
+#include <klistview.h>
+
+#include <qguardedptr.h>
+
+class KexiConnSelectorBase;
+
+//! helper class
+class ConnectionDataLVItem : public QListViewItem
+{
+ public:
+ ConnectionDataLVItem(KexiDB::ConnectionData *data,
+ const KexiDB::Driver::Info& info, QListView *list);
+ ~ConnectionDataLVItem();
+
+ void update(const KexiDB::Driver::Info& info);
+ KexiDB::ConnectionData *data() const { return m_data; }
+
+ protected:
+ KexiDB::ConnectionData *m_data;
+};
+
+
+//class KexiOpenExistingFile;
+class KexiConnSelectorWidgetPrivate;
+
+/*! Widget that allows to select a database connection (without choosing database itself)
+*/
+class KEXIMAIN_EXPORT KexiConnSelectorWidget : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ enum ConnType { FileBased=1, ServerBased=2 };
+
+ /*! Constructs a KexiConnSelector which contain \a conn_set as connection set.
+ \a conn_set can be altered, because Add/Edit/Remove buttons are available
+ to users. \a startDirOrVariable can be provided to specify a start dir for file browser
+ (it can also contain a configuration variable name with ":" prefix as described
+ in KRecentDirs documentation). */
+ KexiConnSelectorWidget( KexiDBConnectionSet& conn_set,
+ const QString& startDirOrVariable,
+ QWidget* parent = 0, const char* name = 0 );
+
+ virtual ~KexiConnSelectorWidget();
+
+ /*! After accepting this dialog this method returns wherher user selected
+ file- or server- based connection (ConnType enum). */
+ int selectedConnectionType() const;
+
+ /*! \return data of selected connection, if server-based connection was selected.
+ Returns NULL if no selection has been made or file-based connection
+ has been selected.
+ @see selectedConnectionType()
+ */
+ KexiDB::ConnectionData* selectedConnectionData() const;
+
+ /*! \return the name of database file, if file-based connection was selected.
+ Returns null string if no selection has been made or server-based connection
+ has been selected.
+ @see selectedConnectionType()
+ */
+ QString selectedFileName();
+
+ /*! Sets selected filename to \a fileName.
+ Only works when selectedConnectionType()==FileBased. */
+ void setSelectedFileName(const QString& fileName);
+
+// //! Usable when we want to do other things for "back" button
+// void disconnectShowSimpleConnButton();
+
+ QListView* connectionsList() const;
+
+ KexiConnSelectorBase *m_remote;
+// KexiOpenExistingFile *m_file;
+ KexiStartupFileDialog *m_fileDlg;
+
+ /*! If true, user will be asked to accept overwriting existing project.
+ This is true by default. */
+ void setConfirmOverwrites(bool set);
+
+ bool confirmOverwrites() const;
+
+ signals:
+ void connectionItemExecuted(ConnectionDataLVItem *item);
+ void connectionItemHighlighted(ConnectionDataLVItem *item);
+
+ public slots:
+ void showSimpleConn();
+ void showAdvancedConn();
+ virtual void setFocus();
+
+ /*! Hides helpers on the server based connection page
+ (sometimes it's convenient not to have these):
+ - "Select existing database server's connection..." (label at the top)
+ - "Click "Back" button" (label at the bottom)
+ - "Back" button itself */
+ void hideHelpers();
+ void hideConnectonIcon();
+
+ protected slots:
+ void slotConnectionItemExecuted(QListViewItem *item);
+ void slotRemoteAddBtnClicked();
+ void slotRemoteEditBtnClicked();
+ void slotRemoteRemoveBtnClicked();
+ void slotConnectionSelectionChanged();
+ void slotPrjTypeSelected(int id);
+
+ private:
+ ConnectionDataLVItem* addConnectionData( KexiDB::ConnectionData* data );
+ ConnectionDataLVItem* selectedConnectionDataItem() const;
+
+ KexiConnSelectorWidgetPrivate *d;
+};
+
+#endif // KEXICONNSELECTOR_H
diff --git a/kexi/main/startup/KexiConnSelectorBase.ui b/kexi/main/startup/KexiConnSelectorBase.ui
new file mode 100644
index 00000000..dde800f3
--- /dev/null
+++ b/kexi/main/startup/KexiConnSelectorBase.ui
@@ -0,0 +1,285 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KexiConnSelectorBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiConnSelectorBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>628</width>
+ <height>289</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QListView" row="1" column="0" rowspan="1" colspan="6">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Server Information</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>list</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="selectionMode">
+ <enum>Single</enum>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="showSortIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="4">
+ <property name="name">
+ <cstring>btn_edit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="3">
+ <property name="name">
+ <cstring>btn_add</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="5">
+ <property name="name">
+ <cstring>btn_remove</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ </widget>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="3" column="4">
+ <property name="name">
+ <cstring>spacer4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>41</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QGroupBox" row="2" column="0" rowspan="2" colspan="2">
+ <property name="name">
+ <cstring>descGroupBox</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>80</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Description</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>2</number>
+ </property>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>descriptionEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="textFormat">
+ <enum>PlainText</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ <property name="tabChangesFocus">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLabel" row="0" column="1" rowspan="1" colspan="5">
+ <property name="name">
+ <cstring>label</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Select Existing Database Server's Connection From the List Below&lt;/b&gt;
+&lt;p&gt;You will see existing Kexi projects available for the selected connection. Here you may also add, edit or remove connections from the list.
+</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>list</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>icon</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>list</tabstop>
+ <tabstop>btn_add</tabstop>
+ <tabstop>btn_edit</tabstop>
+ <tabstop>btn_remove</tabstop>
+ <tabstop>descriptionEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kexi/main/startup/KexiDBTitlePage.cpp b/kexi/main/startup/KexiDBTitlePage.cpp
new file mode 100644
index 00000000..3b048793
--- /dev/null
+++ b/kexi/main/startup/KexiDBTitlePage.cpp
@@ -0,0 +1,35 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiDBTitlePage.h"
+
+#include <qlabel.h>
+
+KexiDBTitlePage::KexiDBTitlePage( const QString& labelText, QWidget* parent, const char* name )
+ : KexiDBTitlePageBase( parent, name )
+{
+ if (!labelText.isEmpty())
+ label->setText(labelText);
+}
+
+KexiDBTitlePage::~KexiDBTitlePage()
+{
+}
+
+#include "KexiDBTitlePage.moc"
diff --git a/kexi/main/startup/KexiDBTitlePage.h b/kexi/main/startup/KexiDBTitlePage.h
new file mode 100644
index 00000000..98341946
--- /dev/null
+++ b/kexi/main/startup/KexiDBTitlePage.h
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KEXIDBTITLEPAGE_H
+#define KEXIDBTITLEPAGE_H
+
+#include "KexiDBTitlePageBase.h"
+
+//! @short A helper widget used to displaying a line edit with a label and layout
+class KEXIMAIN_EXPORT KexiDBTitlePage : public KexiDBTitlePageBase
+{
+ Q_OBJECT
+
+public:
+ //! Constructs title page. \a labelText can be provided to change default
+ //! "Project caption:" label.
+ KexiDBTitlePage( const QString& labelText, QWidget* parent = 0, const char* name = 0 );
+ ~KexiDBTitlePage();
+
+protected slots:
+ virtual void languageChange() { KexiDBTitlePageBase::languageChange(); }
+
+};
+
+#endif // KEXIDBTITLEPAGE_H
+
diff --git a/kexi/main/startup/KexiDBTitlePageBase.ui b/kexi/main/startup/KexiDBTitlePageBase.ui
new file mode 100644
index 00000000..991bc73f
--- /dev/null
+++ b/kexi/main/startup/KexiDBTitlePageBase.ui
@@ -0,0 +1,94 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KexiDBTitlePageBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiDBTitlePageBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>379</width>
+ <height>87</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>label</cstring>
+ </property>
+ <property name="text">
+ <string>Project caption: </string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>le_caption</cstring>
+ </property>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>111</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>le_caption</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>2</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kexi/main/startup/KexiNewPrjTypeSelector.ui b/kexi/main/startup/KexiNewPrjTypeSelector.ui
new file mode 100644
index 00000000..30adfb06
--- /dev/null
+++ b/kexi/main/startup/KexiNewPrjTypeSelector.ui
@@ -0,0 +1,94 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KexiNewPrjTypeSelector</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiNewPrjTypeSelector</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>328</width>
+ <height>203</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KListView" row="1" column="0">
+ <column>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>lv_types</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lbl</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Kexi will create a new database project. Select a storage method which will be used to store the new project.
+</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+</tabstops>
+<functions>
+ <function access="private" specifier="non virtual">init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/kexi/main/startup/KexiNewProjectWizard.cpp b/kexi/main/startup/KexiNewProjectWizard.cpp
new file mode 100644
index 00000000..15102864
--- /dev/null
+++ b/kexi/main/startup/KexiNewProjectWizard.cpp
@@ -0,0 +1,422 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiNewProjectWizard.h"
+
+#include "KexiConnSelector.h"
+#include "KexiConnSelectorBase.h"
+#include "KexiNewPrjTypeSelector.h"
+#include "KexiOpenExistingFile.h"
+#include "KexiDBTitlePage.h"
+#include "KexiServerDBNamePage.h"
+#include "KexiProjectSelector.h"
+#include "kexi.h"
+
+#include <kexiutils/identifier.h>
+#include <kexiutils/utils.h>
+#include <kexiguimsghandler.h>
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klistview.h>
+#include <kurlcombobox.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+
+#include <qobjectlist.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qheader.h>
+
+//! @internal
+class KexiNewProjectWizardPrivate
+{
+ public:
+ KexiNewProjectWizardPrivate()
+ {
+ le_dbname_txtchanged_disable = false;
+ le_dbname_autofill = true;
+// conndata_to_show = 0;
+// project_set_to_show = 0;
+ }
+ ~KexiNewProjectWizardPrivate()
+ {
+// delete conndata_to_show;
+// delete project_set_to_show;
+ delete msgHandler;
+ }
+// KListView *lv_types;
+ KListViewItem *lvi_file, *lvi_server;
+ QString chk_file_txt, chk_server_txt; //!< helper
+
+ QString server_db_name_dblist_lbl_txt; //!< helper
+
+ //for displaying db list of the selected conn.
+ QGuardedPtr<KexiDB::ConnectionData> conndata_to_show;
+ KexiProjectSet *project_set_to_show;
+
+ KexiGUIMessageHandler* msgHandler;
+
+ bool le_dbname_txtchanged_disable : 1;
+ bool le_dbname_autofill : 1;
+};
+
+KexiNewProjectWizard::KexiNewProjectWizard(KexiDBConnectionSet& conn_set,
+ QWidget *parent, const char *name, bool modal, WFlags f)
+: KWizard(parent, name, modal, f)
+, d(new KexiNewProjectWizardPrivate() )
+{
+ d->msgHandler = new KexiGUIMessageHandler(this);
+ setIcon( DesktopIcon("filenew") );
+ setCaption( i18n("Creating New Project") );
+ finishButton()->setText(i18n("Create"));
+
+ //page: type selector
+ m_prjtype_sel = new KexiNewPrjTypeSelector(this, "KexiNewPrjTypeSelector");
+// lv_types = new KListView(m_prjtype_sel, "types listview");
+// m_prjtype_sel->lv_types->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum, 0, 2));
+#if KDE_IS_VERSION(3,3,9)
+ m_prjtype_sel->lv_types->setShadeSortColumn(false);
+#endif
+ m_prjtype_sel->lv_types->header()->hide();
+ m_prjtype_sel->lv_types->setSorting(-1);
+ m_prjtype_sel->lv_types->setAlternateBackground(QColor()); //disable altering
+ m_prjtype_sel->lv_types->setItemMargin( KDialogBase::marginHint() );
+ QString none;
+ d->lvi_file = new KListViewItem( m_prjtype_sel->lv_types, i18n("New Project Stored in File") );
+ d->lvi_file->setPixmap(0,
+ KGlobal::iconLoader()->loadIcon( KMimeType::mimeType(
+ KexiDB::Driver::defaultFileBasedDriverMimeType() )->icon(none,0), KIcon::Desktop
+ )
+ );
+ d->lvi_file->setMultiLinesEnabled( true );
+ d->lvi_server = new KListViewItem( m_prjtype_sel->lv_types, d->lvi_file,
+ i18n("New Project Stored on Database Server") );
+ d->lvi_server->setPixmap(0, DesktopIcon("network") );
+ d->lvi_server->setMultiLinesEnabled( true );
+// m_prjtype_sel->lv_types->resize(d->m_prjtype_sel->lv_types->width(), d->lvi_file->height()*3);
+ m_prjtype_sel->lv_types->setFocus();
+// QString txt_dns = i18n("Don't show me this question again.");
+// d->chk_file_txt = m_prjtype_sel->chk_always->text() +"\n"+txt_dns;
+// d->chk_server_txt = i18n("Always &use database server for creating new projects.")
+// +"\n"+txt_dns;
+
+ connect(m_prjtype_sel->lv_types,SIGNAL(executed(QListViewItem*)),this,SLOT(slotLvTypesExecuted(QListViewItem*)));
+ connect(m_prjtype_sel->lv_types,SIGNAL(returnPressed(QListViewItem*)),this,SLOT(slotLvTypesExecuted(QListViewItem*)));
+ connect(m_prjtype_sel->lv_types,SIGNAL(selectionChanged( QListViewItem*)),this,SLOT(slotLvTypesSelected(QListViewItem*)));
+
+// static_cast<QVBoxLayout*>(m_prjtype_sel->layout())->insertWidget(1,d->m_prjtype_sel->lv_types);
+// static_cast<QVBoxLayout*>(m_prjtype_sel->layout())->insertStretch(3,1);
+// updateGeometry();
+
+ addPage(m_prjtype_sel, i18n("Select Storage Method"));
+// d->m_prjtype_sel->lv_types->setMinimumHeight(QMAX(d->lvi_file->height(),d->lvi_server->height())+25);
+
+ //page: db title
+ m_db_title = new KexiDBTitlePage(QString::null, this, "KexiDBTitlePage");
+ addPage(m_db_title, i18n("Select Project's Caption"));
+
+ //page: connection selector
+ m_conn_sel_widget = new QWidget(this);
+ QVBoxLayout* conn_sel_lyr = new QVBoxLayout(m_conn_sel_widget);
+ QLabel *conn_sel_label = new QLabel(i18n("Enter a new Kexi project's file name:"), m_conn_sel_widget);
+ conn_sel_label->setAlignment(Qt::AlignAuto|Qt::AlignTop|Qt::WordBreak);
+ conn_sel_lyr->addWidget( conn_sel_label );
+ conn_sel_lyr->addSpacing(KDialogBase::spacingHint());
+
+ m_conn_sel = new KexiConnSelectorWidget(conn_set, ":OpenExistingOrCreateNewProject",
+ m_conn_sel_widget, "KexiConnSelectorWidget");
+ conn_sel_lyr->addWidget( m_conn_sel );
+
+ //"Select database server connection"
+// m_conn_sel->m_file->btn_advanced->hide();
+// m_conn_sel->m_file->label->hide();
+//TODO m_conn_sel->m_file->lbl->setText( i18n("Enter a new Kexi project's file name:") );
+ m_conn_sel->hideHelpers();
+
+ m_conn_sel->m_remote->label->setText(
+ i18n("Select database server's connection you wish to use to create a new Kexi project. "
+ "<p>Here you may also add, edit or remove connections from the list."));
+// m_conn_sel->m_remote->label_back->hide();
+// m_conn_sel->m_remote->btn_back->hide();
+
+ m_conn_sel->showSimpleConn();
+ //anyway, db files will be _saved_
+ m_conn_sel->m_fileDlg->setMode( KexiStartupFileDialog::SavingFileBasedDB );
+// m_conn_sel->m_fileDlg->setMode( KFile::LocalOnly | KFile::File );
+// m_conn_sel->m_fileDlg->setOperationMode( KFileDialog::Saving );
+////js connect(m_conn_sel->m_fileDlg,SIGNAL(rejected()),this,SLOT(reject()));
+// connect(m_conn_sel->m_fileDlg,SIGNAL(fileHighlighted(const QString&)),this,SLOT(slotFileHighlighted(const QString&)));
+ connect(m_conn_sel->m_fileDlg,SIGNAL(accepted()),this,SLOT(accept()));
+ m_conn_sel->showAdvancedConn();
+ connect(m_conn_sel,SIGNAL(connectionItemExecuted(ConnectionDataLVItem*)),
+ this,SLOT(next()));
+
+ addPage(m_conn_sel_widget, i18n("Select Project's Location"));
+
+ //page: server db name
+ m_server_db_name = new KexiServerDBNamePage(this, "KexiServerDBNamePage");
+ d->server_db_name_dblist_lbl_txt = i18n("Existing project databases on <b>%1</b> database server:");
+ connect(m_server_db_name->le_caption, SIGNAL(textChanged(const QString&)),
+ this,SLOT(slotServerDBCaptionTxtChanged(const QString&)));
+ connect(m_server_db_name->le_dbname, SIGNAL(textChanged(const QString&)),
+ this,SLOT(slotServerDBNameTxtChanged(const QString&)));
+ connect(m_server_db_name->le_caption, SIGNAL(returnPressed()),
+ this,SLOT(accept()));
+ connect(m_server_db_name->le_dbname, SIGNAL(returnPressed()),
+ this,SLOT(accept()));
+ m_server_db_name->le_caption->setText(i18n("New database"));
+ m_server_db_name->le_dbname->setValidator(new KexiUtils::IdentifierValidator(this, "id_val"));
+ m_project_selector = new KexiProjectSelectorWidget(
+ m_server_db_name->frm_dblist, "KexiProjectSelectorWidget", 0, false, false );
+ GLUE_WIDGET(m_project_selector, m_server_db_name->frm_dblist);
+ m_project_selector->setFocusPolicy(NoFocus);
+ m_project_selector->setSelectable(false);
+
+ addPage(m_server_db_name, i18n("Select Project's Caption & Database Name"));
+
+ setFinishEnabled(m_prjtype_sel,false);
+ setFinishEnabled(m_db_title,false);
+ setFinishEnabled(m_server_db_name,true);
+
+ //finish:
+ updateGeometry();
+ m_prjtype_sel->lv_types->setSelected(d->lvi_file, true);
+}
+
+KexiNewProjectWizard::~KexiNewProjectWizard()
+{
+ delete d;
+}
+
+void KexiNewProjectWizard::show()
+{
+ KDialog::centerOnScreen(this);
+ KWizard::show();
+}
+
+void KexiNewProjectWizard::slotLvTypesExecuted(QListViewItem *)
+{
+ next();
+}
+
+void KexiNewProjectWizard::slotLvTypesSelected(QListViewItem *item)
+{
+/* if (item==d->lvi_file) {
+ m_prjtype_sel->chk_always->setText(d->chk_file_txt);
+ }
+ else if (item==d->lvi_server) {
+ m_prjtype_sel->chk_always->setText(d->chk_server_txt);
+ }*/
+ setAppropriate( m_db_title, item==d->lvi_file );
+ setAppropriate( m_server_db_name, item==d->lvi_server );
+}
+
+void KexiNewProjectWizard::showPage(QWidget *page)
+{
+ if (page==m_prjtype_sel) {//p 1
+ m_prjtype_sel->lv_types->setFocus();
+ m_prjtype_sel->lv_types->setCurrentItem(m_prjtype_sel->lv_types->currentItem());
+ } else if (page==m_db_title) {//p 2
+ if (m_db_title->le_caption->text().stripWhiteSpace().isEmpty())
+ m_db_title->le_caption->setText(i18n("New database"));
+ m_db_title->le_caption->selectAll();
+ m_db_title->le_caption->setFocus();
+ } else if (page==m_conn_sel_widget) {//p 3
+ if (m_prjtype_sel->lv_types->currentItem()==d->lvi_file) {
+ m_conn_sel->showSimpleConn();
+ QString fn = KexiUtils::string2FileName( m_db_title->le_caption->text() );
+ if (!fn.endsWith(".kexi"))
+ fn += ".kexi";
+ m_conn_sel->m_fileDlg->setLocationText(fn);
+ setFinishEnabled(m_conn_sel_widget,true);
+ m_conn_sel->setFocus();
+ }
+ else {
+ m_conn_sel->showAdvancedConn();
+ setFinishEnabled(m_conn_sel_widget,false);
+ m_conn_sel->setFocus();
+ m_server_db_name->le_caption->selectAll();
+ }
+ } else if (page==m_server_db_name) {
+ if (m_conn_sel->selectedConnectionData()
+ && (static_cast<KexiDB::ConnectionData*>(d->conndata_to_show) != m_conn_sel->selectedConnectionData())) {
+ m_project_selector->setProjectSet(0);
+// delete d->project_set_to_show;
+ d->conndata_to_show = 0;
+ d->project_set_to_show = new KexiProjectSet(*m_conn_sel->selectedConnectionData(), d->msgHandler);
+ if (d->project_set_to_show->error()) {
+ delete d->project_set_to_show;
+ d->project_set_to_show = 0;
+ return;
+ }
+ d->conndata_to_show = m_conn_sel->selectedConnectionData();
+ //-refresh projects list
+ m_project_selector->setProjectSet( d->project_set_to_show );
+ }
+ }
+ KWizard::showPage(page);
+}
+
+void KexiNewProjectWizard::next()
+{
+ //let's check if move to next page is allowed:
+ if (currentPage()==m_db_title) { //pg 2
+ if (m_db_title->le_caption->text().stripWhiteSpace().isEmpty()) {
+ KMessageBox::information(this, i18n("Enter project caption."));
+ m_db_title->le_caption->setText("");
+ m_db_title->le_caption->setFocus();
+ return;
+ }
+ } else if (currentPage()==m_conn_sel_widget) {//p 3
+ if (m_prjtype_sel->lv_types->currentItem()==d->lvi_file) {
+ //test for db file selection
+ }
+ else {
+ //test for db conn selection
+ if (!m_conn_sel->selectedConnectionData()) {
+ KMessageBox::information(this, i18n("Select server connection for a new project."));
+ return;
+ }
+ m_project_selector->label->setText(
+ d->server_db_name_dblist_lbl_txt.arg(m_conn_sel->selectedConnectionData()->serverInfoString(false)) );
+ m_server_db_name->le_caption->setFocus();
+
+ }
+ }
+ KWizard::next();
+}
+
+void KexiNewProjectWizard::accept()
+{
+ if (m_prjtype_sel->lv_types->currentItem()==d->lvi_file) {//FILE:
+ //check if new db file name is ok
+ kdDebug() << "********** sender() " << sender()->className() << endl;
+ if (sender()==finishButton()) { /*(only if signal does not come from filedialog)*/
+ kdDebug() << "********** sender()==finishButton() ********" << endl;
+// if (!m_conn_sel->m_fileDlg->checkURL()) {
+ if (!m_conn_sel->m_fileDlg->checkFileName()) {
+ return;
+ }
+ }
+ } else {//SERVER:
+ //check if we have enough of data
+ if (m_server_db_name->le_caption->text().stripWhiteSpace().isEmpty()) {
+ KMessageBox::information(this, i18n("Enter project caption."));
+ m_server_db_name->le_caption->setText("");
+ m_server_db_name->le_caption->setFocus();
+ return;
+ }
+ QString dbname = m_server_db_name->le_dbname->text().stripWhiteSpace();
+ if (dbname.isEmpty()) {
+ KMessageBox::information(this, i18n("Enter project's database name."));
+ m_server_db_name->le_dbname->setText("");
+ m_server_db_name->le_dbname->setFocus();
+ return;
+ }
+ //check for duplicated dbname
+ if (m_conn_sel->confirmOverwrites() && m_project_selector->projectSet() && m_project_selector->projectSet()
+ ->findProject( m_server_db_name->le_dbname->text() )) {
+ if (KMessageBox::Continue!=KMessageBox::warningContinueCancel( this, "<qt>"
+ +i18n("<b>A project with database name \"%1\" already exists</b>"
+ "<p>Do you want to delete it and create a new one?")
+ .arg( m_server_db_name->le_dbname->text() ), QString::null, KStdGuiItem::del(),
+ QString::null, KMessageBox::Notify|KMessageBox::Dangerous ))
+ {
+ m_server_db_name->le_dbname->setFocus();
+ return;
+ }
+ }
+ }
+
+ KWizard::accept();
+}
+
+void KexiNewProjectWizard::done(int r)
+{
+/* //save state (always, no matter if dialog is accepted or not)
+ KGlobal::config()->setGroup("Startup");
+ if (!m_prjtype_sel->chk_always->isChecked())
+ KGlobal::config()->deleteEntry("DefaultStorageForNewProjects");
+ else if (m_prjtype_sel->lv_types->currentItem()==d->lvi_file)
+ KGlobal::config()->writeEntry("DefaultStorageForNewProjects","File");
+ else
+ KGlobal::config()->writeEntry("DefaultStorageForNewProjects","Server");*/
+
+ KGlobal::config()->sync();
+ KWizard::done(r);
+}
+
+QString KexiNewProjectWizard::projectDBName() const
+{
+ if (m_prjtype_sel->lv_types->currentItem()==d->lvi_server)
+ return m_server_db_name->le_dbname->text();
+ return m_conn_sel->selectedFileName();
+}
+
+QString KexiNewProjectWizard::projectCaption() const
+{
+ if (m_prjtype_sel->lv_types->currentItem()==d->lvi_server) {
+ return m_server_db_name->le_caption->text();
+ }
+ return m_db_title->le_caption->text();
+}
+
+KexiDB::ConnectionData* KexiNewProjectWizard::projectConnectionData() const
+{
+ if (m_prjtype_sel->lv_types->currentItem()==d->lvi_file)
+ return 0;
+ return m_conn_sel->selectedConnectionData();
+}
+
+void KexiNewProjectWizard::slotServerDBCaptionTxtChanged(const QString &capt)
+{
+ if (m_server_db_name->le_dbname->text().isEmpty())
+ d->le_dbname_autofill=true;
+ if (d->le_dbname_autofill) {
+ d->le_dbname_txtchanged_disable = true;
+ QString captionAsId = KexiUtils::string2Identifier(capt);
+ m_server_db_name->le_dbname->setText(captionAsId);
+ d->le_dbname_txtchanged_disable = false;
+ }
+}
+
+void KexiNewProjectWizard::slotServerDBNameTxtChanged(const QString &)
+{
+ if (d->le_dbname_txtchanged_disable)
+ return;
+ d->le_dbname_autofill = false;
+}
+
+/*! If true, user will be asked to accept overwriting existing file.
+ This is true by default. */
+void KexiNewProjectWizard::setConfirmOverwrites(bool set)
+{
+ m_conn_sel->setConfirmOverwrites(set);
+}
+
+
+#include "KexiNewProjectWizard.moc"
+
diff --git a/kexi/main/startup/KexiNewProjectWizard.h b/kexi/main/startup/KexiNewProjectWizard.h
new file mode 100644
index 00000000..9f9eaa62
--- /dev/null
+++ b/kexi/main/startup/KexiNewProjectWizard.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KexiNewProjectWizard_H
+#define KexiNewProjectWizard_H
+
+#include "kexidbconnectionset.h"
+#include <kexidb/connectiondata.h>
+
+#include <kwizard.h>
+
+class QListViewItem;
+
+class KexiNewPrjTypeSelector;
+class KexiConnSelectorWidget;
+class KexiNewProjectWizardPrivate;
+class KexiDBTitlePage;
+class KexiServerDBNamePage;
+class KexiProjectSelectorWidget;
+
+class KEXIMAIN_EXPORT KexiNewProjectWizard : public KWizard
+{
+ Q_OBJECT
+ public:
+ KexiNewProjectWizard(KexiDBConnectionSet& conn_set, QWidget *parent=0,
+ const char *name=0, bool modal=false, WFlags f=0);
+ ~KexiNewProjectWizard();
+
+ /*! \return name for a new project's database if server-based project
+ type was selected. Returns file name if file-based project was selected. */
+ QString projectDBName() const;
+
+ /*! \return name for a new project. Used for both file- and serever- based projects. */
+ QString projectCaption() const;
+
+ /*! \return data of selected connection for new project,
+ if server-based project type was selected.
+ Returns NULL if no selection has been made or file-based project
+ has been selected. */
+ KexiDB::ConnectionData* projectConnectionData() const;
+
+ /*! Reimplemented for internal reasons */
+ virtual void show();
+
+ /*! If true, user will be asked to accept overwriting existing project.
+ This is true by default. */
+ void setConfirmOverwrites(bool set);
+
+ protected slots:
+ void slotLvTypesSelected(QListViewItem *);
+ void slotLvTypesExecuted(QListViewItem *);
+ void slotServerDBCaptionTxtChanged(const QString &capt);
+ void slotServerDBNameTxtChanged(const QString &n);
+
+ virtual void done(int r);
+ virtual void next();
+ virtual void accept();
+
+ protected:
+ virtual void showPage(QWidget *page);
+
+ KexiNewPrjTypeSelector *m_prjtype_sel;
+ KexiDBTitlePage *m_db_title;
+ KexiServerDBNamePage *m_server_db_name;
+ KexiProjectSelectorWidget* m_project_selector;
+
+ KexiConnSelectorWidget *m_conn_sel;
+ QWidget *m_conn_sel_widget;
+
+ KexiNewProjectWizardPrivate *d;
+};
+
+#endif
+
diff --git a/kexi/main/startup/KexiOpenExistingFile.ui b/kexi/main/startup/KexiOpenExistingFile.ui
new file mode 100644
index 00000000..ae4c05a9
--- /dev/null
+++ b/kexi/main/startup/KexiOpenExistingFile.ui
@@ -0,0 +1,127 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KexiOpenExistingFile</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiOpenExistingFile</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>328</width>
+ <height>108</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>lbl</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Select existing Kexi project file to open:&lt;/b&gt;
+</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>line</cstring>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>8</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>spacer</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>6</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>6</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btn_advanced</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Advanced </string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Click "Advanced" button if you want to find an existing project on a server rather than a file.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>btn_advanced</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kexi/main/startup/KexiProjectSelector.cpp b/kexi/main/startup/KexiProjectSelector.cpp
new file mode 100644
index 00000000..c28ab6d5
--- /dev/null
+++ b/kexi/main/startup/KexiProjectSelector.cpp
@@ -0,0 +1,297 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiProjectSelector.h"
+
+#include <kexidb/drivermanager.h>
+#include <kexidb/connectiondata.h>
+#include "core/kexi.h"
+
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kmimetype.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qlistview.h>
+
+#include <assert.h>
+
+//! @internal
+class KexiProjectSelectorWidgetPrivate
+{
+public:
+ KexiProjectSelectorWidgetPrivate()
+ {
+ selectable = true;
+ }
+ QPixmap fileicon, dbicon;
+ bool showProjectNameColumn : 1;
+ bool showConnectionColumns : 1;
+ bool selectable : 1;
+};
+
+/*================================================================*/
+
+//! helper class
+class ProjectDataLVItem : public QListViewItem
+{
+public:
+ ProjectDataLVItem(KexiProjectData *d,
+ const KexiDB::Driver::Info& info, KexiProjectSelectorWidget *selector )
+ : QListViewItem(selector->list)
+ , data(d)
+ {
+ int colnum = 0;
+ const KexiDB::ConnectionData *cdata = data->constConnectionData();
+ if (selector->d->showProjectNameColumn)
+ setText(colnum++, data->caption()+" ");
+
+ setText(colnum++, data->databaseName()+" ");
+
+ if (selector->d->showConnectionColumns) {
+ QString drvname = info.caption.isEmpty() ? cdata->driverName : info.caption;
+ if (info.fileBased) {
+ setText(colnum++, i18n("File") + " ("+drvname+") " );
+ } else {
+ setText(colnum++, drvname+" " );
+ }
+
+ QString conn;
+ if (!cdata->caption.isEmpty())
+ conn = cdata->caption + ": ";
+ conn += cdata->serverInfoString();
+ setText(3, conn + " ");
+ }
+ }
+ ~ProjectDataLVItem() {}
+
+ KexiProjectData *data;
+};
+
+/*================================================================*/
+
+/*!
+ * Constructs a KexiProjectSelector which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ */
+KexiProjectSelectorWidget::KexiProjectSelectorWidget(
+ QWidget* parent, const char* name,
+ KexiProjectSet* prj_set, bool showProjectNameColumn,
+ bool showConnectionColumns )
+ : KexiProjectSelectorBase( parent, name )
+ ,m_prj_set(prj_set)
+ ,d(new KexiProjectSelectorWidgetPrivate())
+{
+ d->showProjectNameColumn = showProjectNameColumn;
+ d->showConnectionColumns = showConnectionColumns;
+ QString none, iconname = KMimeType::mimeType( KexiDB::Driver::defaultFileBasedDriverMimeType() )->icon(none,0);
+ d->fileicon = KGlobal::iconLoader()->loadIcon( iconname, KIcon::Desktop );
+ setIcon( d->fileicon );
+ d->dbicon = SmallIcon("database");
+// list->setHScrollBarMode( QScrollView::AlwaysOn );
+
+ if (!d->showConnectionColumns) {
+ list->removeColumn(2);
+ list->removeColumn(2);
+ }
+ if (!d->showProjectNameColumn) {
+ list->removeColumn(0);
+ }
+ setFocusProxy(list);
+
+ //show projects
+ setProjectSet( m_prj_set );
+ connect(list,SIGNAL(doubleClicked(QListViewItem*)),this,SLOT(slotItemExecuted(QListViewItem*)));
+ connect(list,SIGNAL(returnPressed(QListViewItem*)),this,SLOT(slotItemExecuted(QListViewItem*)));
+ connect(list,SIGNAL(selectionChanged()),this,SLOT(slotItemSelected()));
+}
+
+/*!
+ * Destroys the object and frees any allocated resources
+ */
+KexiProjectSelectorWidget::~KexiProjectSelectorWidget()
+{
+ delete d;
+}
+
+KexiProjectData* KexiProjectSelectorWidget::selectedProjectData() const
+{
+ ProjectDataLVItem *item = static_cast<ProjectDataLVItem*>(list->selectedItem());
+ if (item)
+ return item->data;
+ return 0;
+}
+
+void KexiProjectSelectorWidget::slotItemExecuted(QListViewItem *item)
+{
+ if (!d->selectable)
+ return;
+ ProjectDataLVItem *ditem = static_cast<ProjectDataLVItem*>(item);
+ if (ditem)
+ emit projectExecuted( ditem->data );
+}
+
+void KexiProjectSelectorWidget::slotItemSelected()
+{
+ if (!d->selectable)
+ return;
+ ProjectDataLVItem *ditem = static_cast<ProjectDataLVItem*>(list->selectedItem());
+ emit selectionChanged( ditem ? ditem->data : 0 );
+}
+
+void KexiProjectSelectorWidget::setProjectSet( KexiProjectSet* prj_set )
+{
+ if (prj_set) {
+ //old list
+ list->clear();
+ }
+ m_prj_set = prj_set;
+ if (!m_prj_set)
+ return;
+//TODO: what with project set's ownership?
+ if (m_prj_set->error()) {
+ kdDebug() << "KexiProjectSelectorWidget::setProjectSet() : m_prj_set->error() !"<<endl;
+ return;
+ }
+ KexiDB::DriverManager manager;
+ KexiProjectData::List prjlist = m_prj_set->list();
+ KexiProjectData *data = prjlist.first();
+ while (data) {
+ KexiDB::Driver::Info info = manager.driverInfo(data->constConnectionData()->driverName);
+ if (!info.name.isEmpty()) {
+ ProjectDataLVItem *item = new ProjectDataLVItem(data, info, this);
+ if (!d->selectable)
+ item->setSelectable(false);
+ if (info.fileBased)
+ item->setPixmap( 0, d->fileicon );
+ else
+ item->setPixmap( 0, d->dbicon );
+ }
+ else {
+ kdWarning() << "KexiProjectSelector::KexiProjectSelector(): no driver found for '"
+ << data->constConnectionData()->driverName << "'!" << endl;
+ }
+ data=prjlist.next();
+ }
+ if (list->firstChild()) {
+ list->setSelected(list->firstChild(),true);
+ }
+}
+
+void KexiProjectSelectorWidget::setSelectable(bool set)
+{
+ if (d->selectable == set)
+ return;
+ d->selectable = set;
+ //update items' state
+ QListViewItemIterator it( list );
+ while ( it.current() ) {
+ it.current()->setSelectable( d->selectable );
+ }
+}
+
+bool KexiProjectSelectorWidget::isSelectable() const
+{
+ return d->selectable;
+}
+
+/*================================================================*/
+
+KexiProjectSelectorDialog::KexiProjectSelectorDialog( QWidget *parent, const char *name,
+ KexiProjectSet* prj_set, bool showProjectNameColumn, bool showConnectionColumns)
+ : KDialogBase( Plain, i18n("Open Recent Project"),
+#ifndef KEXI_NO_UNFINISHED
+ //! @todo re-add Help when doc is available
+ Help |
+#endif
+ Ok | Cancel, Ok, parent, name )
+{
+ init(prj_set, showProjectNameColumn, showConnectionColumns);
+}
+
+KexiProjectSelectorDialog::KexiProjectSelectorDialog( QWidget *parent, const char *name,
+ KexiDB::ConnectionData* cdata,
+ bool showProjectNameColumn, bool showConnectionColumns)
+ : KDialogBase(
+ Plain, i18n("Open Project"),
+#ifndef KEXI_NO_UNFINISHED
+ //! @todo re-add Help when doc is available
+ Help |
+#endif
+ Ok | Cancel, Ok, parent, name, true/*modal*/, false/*sep*/ )
+{
+ setButtonGuiItem(Ok, KGuiItem(i18n("&Open"), "fileopen", i18n("Open Database Connection")));
+ assert(cdata);
+ if (!cdata)
+ return;
+ KexiProjectSet *prj_set = new KexiProjectSet( *cdata );
+ init(prj_set, showProjectNameColumn, showConnectionColumns);
+
+ m_sel->label->setText( i18n("Select a project on <b>%1</b> database server to open:")
+ .arg(cdata->serverInfoString(false)) );
+}
+
+KexiProjectSelectorDialog::~KexiProjectSelectorDialog()
+{
+}
+
+void KexiProjectSelectorDialog::init(KexiProjectSet* prj_set, bool showProjectNameColumn,
+ bool showConnectionColumns)
+{
+ setSizeGripEnabled(true);
+
+ QVBoxLayout *lyr = new QVBoxLayout(plainPage(), 0, KDialogBase::spacingHint(), "lyr");
+ m_sel = new KexiProjectSelectorWidget(plainPage(), "sel",
+ prj_set, showProjectNameColumn, showConnectionColumns);
+ lyr->addWidget(m_sel);
+ setIcon(*m_sel->icon());
+ m_sel->setFocus();
+
+ connect(m_sel,SIGNAL(projectExecuted(KexiProjectData*)),
+ this,SLOT(slotProjectExecuted(KexiProjectData*)));
+ connect(m_sel,SIGNAL(selectionChanged(KexiProjectData*)),
+ this,SLOT(slotProjectSelectionChanged(KexiProjectData*)));
+}
+
+KexiProjectData* KexiProjectSelectorDialog::selectedProjectData() const
+{
+ return m_sel->selectedProjectData();
+}
+
+void KexiProjectSelectorDialog::slotProjectExecuted(KexiProjectData*)
+{
+ accept();
+}
+
+void KexiProjectSelectorDialog::slotProjectSelectionChanged(KexiProjectData* pdata)
+{
+ enableButtonOK(pdata);
+}
+
+void KexiProjectSelectorDialog::show()
+{
+ KDialogBase::show();
+ KDialog::centerOnScreen(this);
+}
+
+#include "KexiProjectSelector.moc"
diff --git a/kexi/main/startup/KexiProjectSelector.h b/kexi/main/startup/KexiProjectSelector.h
new file mode 100644
index 00000000..3151be3b
--- /dev/null
+++ b/kexi/main/startup/KexiProjectSelector.h
@@ -0,0 +1,134 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Jaroslaw Staniek <js@iidea.pl>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KEXIPROJECTSELECTOR_H
+#define KEXIPROJECTSELECTOR_H
+
+#include "KexiProjectSelectorBase.h"
+#include "kexiprojectset.h"
+
+#include <kdialogbase.h>
+#include <qwidgetstack.h>
+
+class KexiNewFileDBWidget;
+class KexiProjectSelectorWidgetPrivate;
+
+/*! Widget that allows to select a kexi project (or database)
+*/
+class KEXIMAIN_EXPORT KexiProjectSelectorWidget : public KexiProjectSelectorBase
+{
+ Q_OBJECT
+
+public:
+// enum ConnType { FileBased=1, ServerBased=2 };
+
+ /*! Constructs a project selector widget.
+ If \a showProjectNameColumn is true (the default)
+ project names' column is visible. If \a showConnectionColumns is true (the default)
+ information about database driver and connection columns are added.
+ \a prj_set may be NULL - you can assign a set later with setProjectSet().
+ */
+ KexiProjectSelectorWidget( QWidget* parent = 0, const char* name = 0,
+ KexiProjectSet* prj_set = 0, bool showProjectNameColumn = true,
+ bool showConnectionColumns = true );
+
+ ~KexiProjectSelectorWidget();
+
+ /*! \return data of selected project. Returns NULL if no selection has been made.
+ */
+ KexiProjectData* selectedProjectData() const;
+
+ /*! Assigns a new project set \a prj_set. Old project set is not destoyed
+ - it is just left unassigned.
+ If new project set is in error state (Object::error() == true), nothing is displayed. */
+ void setProjectSet( KexiProjectSet* prj_set );
+
+ /*! \return currently assigned project set or NULL if no project set is assigned. */
+ inline KexiProjectSet *projectSet() { return m_prj_set; }
+
+ /*! Sets selectable state on or off. In this state one project item can be selected
+ and executed by mouse double clicking or return key pressing.
+ The property is true by default. */
+ void setSelectable(bool set);
+
+ /*! \return if a witget has selectable state set. */
+ bool isSelectable() const;
+
+public slots:
+
+signals:
+ void projectExecuted(KexiProjectData*);
+ void selectionChanged(KexiProjectData*);
+
+protected slots:
+ void slotItemExecuted(QListViewItem*);
+ void slotItemSelected();
+ virtual void languageChange() { KexiProjectSelectorBase::languageChange(); }
+
+protected:
+ KexiProjectSet *m_prj_set;
+
+ KexiProjectSelectorWidgetPrivate *d;
+
+ friend class ProjectDataLVItem;
+};
+
+/*! Dialog container for KexiProjectSelectorWidget */
+class KexiProjectSelectorDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /*! Constructor 1, used for displaying recent projects list
+ Label "there are recently opened projects" is displayed automatically
+ */
+ KexiProjectSelectorDialog( QWidget *parent, const char *name,
+ KexiProjectSet* prj_set,
+ bool showProjectNameColumn = true, bool showConnectionColumns = true);
+
+ /*! Constructor 2, used for displaying projects list for given connection
+ Label "Select one of these existing projects on server" is displayed automatically
+ You should test if project set was properly loaded using projectSet()->error().
+ */
+ KexiProjectSelectorDialog( QWidget *parent, const char *name,
+ KexiDB::ConnectionData* cdata,
+ bool showProjectNameColumn = true, bool showConnectionColumns = true);
+
+ ~KexiProjectSelectorDialog();
+
+ /*! \return data of selected project. Returns NULL if no selection has been made.
+ */
+ KexiProjectData* selectedProjectData() const;
+
+ /*! \return currently assigned project set or NULL if no project set is assigned. */
+ inline KexiProjectSet *projectSet() { return m_sel->projectSet(); }
+
+ virtual void show();
+
+protected slots:
+ void slotProjectExecuted(KexiProjectData*);
+ void slotProjectSelectionChanged(KexiProjectData*);
+
+protected:
+ void init(KexiProjectSet* prj_set, bool showProjectNameColumn, bool showConnectionColumns);
+
+ KexiProjectSelectorWidget* m_sel;
+};
+
+#endif
+
diff --git a/kexi/main/startup/KexiProjectSelectorBase.ui b/kexi/main/startup/KexiProjectSelectorBase.ui
new file mode 100644
index 00000000..4d51751b
--- /dev/null
+++ b/kexi/main/startup/KexiProjectSelectorBase.ui
@@ -0,0 +1,128 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KexiProjectSelectorBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiProjectSelectorBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>405</width>
+ <height>164</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;There are Kexi projects you have recently opened.&lt;/b&gt; Select one you wish to open:
+</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignTop</set>
+ </property>
+ </widget>
+ <widget class="QListView">
+ <column>
+ <property name="text">
+ <string>Project Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Database</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Connection</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>list</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="showSortIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>LastColumn</enum>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>list</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kexi/main/startup/KexiServerDBNamePage.ui b/kexi/main/startup/KexiServerDBNamePage.ui
new file mode 100644
index 00000000..3ea61dc3
--- /dev/null
+++ b/kexi/main/startup/KexiServerDBNamePage.ui
@@ -0,0 +1,141 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KexiServerDBNamePage</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KexiServerDBNamePage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>477</width>
+ <height>299</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Project caption: </string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Project's database name: </string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>le_caption</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>le_dbname</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>70</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>70</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QFrame" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>frm_dblist</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>12</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kexi/main/startup/KexiStartup.cpp b/kexi/main/startup/KexiStartup.cpp
new file mode 100644
index 00000000..19ae8d28
--- /dev/null
+++ b/kexi/main/startup/KexiStartup.cpp
@@ -0,0 +1,965 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KexiStartup.h"
+#ifdef Q_WS_WIN
+# include "KexiStartup_p_win.h"
+#else
+# include "KexiStartup_p.h"
+#endif
+
+#include "kexiproject.h"
+#include "kexiprojectdata.h"
+#include "kexiprojectset.h"
+#include "kexiguimsghandler.h"
+
+#include <kexidb/driver.h>
+#include <kexidb/drivermanager.h>
+#include "KexiStartupDialog.h"
+#include "KexiConnSelector.h"
+#include "KexiProjectSelectorBase.h"
+#include "KexiProjectSelector.h"
+#include "KexiNewProjectWizard.h"
+#include <kexidbconnectionwidget.h>
+#include <kexidbshortcutfile.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kcmdlineargs.h>
+#include <kdeversion.h>
+#include <kprogress.h>
+#include <ktextedit.h>
+#include <kstaticdeleter.h>
+#include <kuser.h>
+
+#include <unistd.h>
+
+#include <qcstring.h>
+#include <qapplication.h>
+#include <qlayout.h>
+
+namespace Kexi {
+ static KStaticDeleter<KexiStartupHandler> Kexi_startupHandlerDeleter;
+ KexiStartupHandler* _startupHandler = 0;
+
+ KexiStartupHandler& startupHandler()
+ {
+ if (!_startupHandler)
+ Kexi_startupHandlerDeleter.setObject( _startupHandler, new KexiStartupHandler() );
+ return *_startupHandler;
+ }
+}
+
+//---------------------------------
+
+//! @internal
+class KexiStartupHandlerPrivate
+{
+ public:
+ KexiStartupHandlerPrivate()
+ : passwordDialog(0)//, showConnectionDetailsExecuted(false)
+ , shortcutFile(0), connShortcutFile(0), connDialog(0), startupDialog(0)
+ {
+ }
+
+ ~KexiStartupHandlerPrivate()
+ {
+ delete passwordDialog;
+ delete connDialog;
+ delete startupDialog;
+ }
+
+ KexiDBPasswordDialog* passwordDialog;
+// bool showConnectionDetailsExecuted : 1;
+ KexiDBShortcutFile *shortcutFile;
+ KexiDBConnShortcutFile *connShortcutFile;
+ KexiDBConnectionDialog *connDialog;
+ QString shortcutFileGroupKey;
+ KexiStartupDialog *startupDialog;
+};
+
+//---------------------------------
+
+static bool stripQuotes(const QString &item, QString &name)
+{
+ if (item.left(1)=="\"" && item.right(1)=="\"") {
+ name = item.mid(1, item.length()-2);
+ return true;
+ }
+ name = item;
+ return false;
+}
+
+void updateProgressBar(KProgressDialog *pd, char *buffer, int buflen)
+{
+ char *p = buffer;
+ QCString line(80);
+ for (int i=0; i<buflen; i++, p++) {
+ if ((i==0 || buffer[i-1]=='\n') && buffer[i]=='%') {
+ bool ok;
+ int j=0;
+// char *q=++p;
+ ++i;
+ line="";
+ for (;i<buflen && *p>='0' && *p<='9'; j++, i++, p++)
+ line+=QChar(*p);
+ --i; --p;
+ int percent = line.toInt(&ok);
+ if (ok && percent>=0 && percent<=100 && pd->progressBar()->progress()<percent) {
+// kdDebug() << percent << endl;
+ pd->progressBar()->setProgress(percent);
+ qApp->processEvents(100);
+ }
+ }
+ }
+}
+
+//---------------------------------
+
+KexiDBPasswordDialog::KexiDBPasswordDialog(QWidget *parent, KexiDB::ConnectionData& cdata, bool showDetailsButton)
+ : KPasswordDialog( KPasswordDialog::Password, false/*keep*/,
+ showDetailsButton ? (int)KDialogBase::User1 : 0, parent )
+ , m_cdata(&cdata)
+ , m_showConnectionDetailsRequested(false)
+{
+ QString msg = "<H2>" + i18n("Opening database") + "</H2><p>"
+ + i18n("Please enter the password.") + "</p>";
+/* msg += cdata.userName.isEmpty() ?
+ "<p>"+i18n("Please enter the password.")
+ : "<p>"+i18n("Please enter the password for user.").arg("<b>"+cdata.userName+"</b>");*/
+
+ QString srv = cdata.serverInfoString(false);
+ if (srv.isEmpty() || srv.lower()=="localhost")
+ srv = i18n("local database server");
+
+ msg += ("</p><p>"+i18n("Database server: %1").arg(QString("<nobr>")+srv+"</nobr>")+"</p>");
+
+ QString usr;
+ if (cdata.userName.isEmpty())
+ usr = i18n("unspecified user", "(unspecified)");
+ else
+ usr = cdata.userName;
+
+ msg += ("<p>"+i18n("Username: %1").arg(usr)+"</p>");
+
+ setPrompt( msg );
+ if (showDetailsButton) {
+ connect( this, SIGNAL(user1Clicked()),
+ this, SLOT(slotShowConnectionDetails()) );
+ setButtonText(KDialogBase::User1, i18n("&Details")+ " >>");
+ }
+ setButtonOK(KGuiItem(i18n("&Open"), "fileopen"));
+}
+
+KexiDBPasswordDialog::~KexiDBPasswordDialog()
+{
+}
+
+void KexiDBPasswordDialog::done(int r)
+{
+ if (r == QDialog::Accepted) {
+ m_cdata->password = QString::fromLatin1(password());
+ }
+// if (d->showConnectionDetailsExecuted || ret == QDialog::Accepted) {
+/* } else {
+ m_action = Exit;
+ return true;
+ }
+ }*/
+ KPasswordDialog::done(r);
+}
+
+void KexiDBPasswordDialog::slotShowConnectionDetails()
+{
+ m_showConnectionDetailsRequested = true;
+ close();
+}
+
+//---------------------------------
+KexiStartupHandler::KexiStartupHandler()
+ : QObject(0,"KexiStartupHandler")
+ , KexiStartupData()
+ , d( new KexiStartupHandlerPrivate() )
+{
+}
+
+KexiStartupHandler::~KexiStartupHandler()
+{
+ delete d;
+}
+
+bool KexiStartupHandler::getAutoopenObjects(KCmdLineArgs *args, const QCString &action_name)
+{
+ QCStringList list = args->getOptionList(action_name);
+ QCStringList::ConstIterator it;
+ bool atLeastOneFound = false;
+ for ( it = list.constBegin(); it!=list.constEnd(); ++it) {
+ QString type_name, obj_name, item=*it;
+ int idx;
+ bool name_required = true;
+ if (action_name=="new") {
+ obj_name = "";
+ stripQuotes(item, type_name);
+ name_required = false;
+ }
+ else {//open, design, text...
+ QString defaultType;
+ if (action_name=="execute")
+ defaultType = "macro";
+ else
+ defaultType = "table";
+
+ //option with " " (set default type)
+ if (stripQuotes(item, obj_name)) {
+ type_name = defaultType;
+ }
+ else if ((idx = item.find(':'))!=-1) {
+ //option with type name specified:
+ type_name = item.left(idx).lower();
+ obj_name = item.mid(idx+1);
+ //optional: remove ""
+ if (obj_name.left(1)=="\"" && obj_name.right(1)=="\"")
+ obj_name = obj_name.mid(1, obj_name.length()-2);
+ }
+ else {
+ //just obj. name: set default type name
+ obj_name = item;
+ type_name = defaultType;
+ }
+ }
+ if (type_name.isEmpty())
+ continue;
+ if (name_required && obj_name.isEmpty())
+ continue;
+
+ KexiProjectData::ObjectInfo info;
+ info["name"]=obj_name;
+ info["type"]=type_name;
+ info["action"]=action_name;
+ //ok, now add info for this object
+ atLeastOneFound = true;
+ if (projectData())
+ projectData()->autoopenObjects.append( info );
+ else
+ return true; //no need to find more because we do not have projectData() anyway
+ } //for
+ return atLeastOneFound;
+}
+
+tristate KexiStartupHandler::init(int /*argc*/, char ** /*argv*/)
+{
+ m_action = DoNothing;
+// d->showConnectionDetailsExecuted = false;
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs(0);
+ if (!args)
+ return true;
+
+ KexiDB::ConnectionData cdata;
+
+ const QString connectionShortcutFileName( args->getOption("connection") );
+ if (!connectionShortcutFileName.isEmpty()) {
+ KexiDBConnShortcutFile connectionShortcut( connectionShortcutFileName );
+ if (!connectionShortcut.loadConnectionData(cdata)) {
+//! @todo Show error message from KexiDBConnShortcutFile when there's one implemented.
+//! For we're displaying generic error msg.
+ KMessageBox::sorry( 0, "<qt>"
+ +i18n("Could not read connection information from connection shortcut "
+ "file <nobr>\"%1\"</nobr>.<br><br>Check whether the file has valid contents.")
+ .arg(QDir::convertSeparators(connectionShortcut.fileName())));
+ return false;
+ }
+ }
+
+ if (!args->getOption("dbdriver").isEmpty())
+ cdata.driverName = args->getOption("dbdriver");
+
+ QString fileType( args->getOption("type").lower() );
+ if (args->count()>0 && (!fileType.isEmpty() && fileType!="project" && fileType!="shortcut" && fileType!="connection")) {
+ KMessageBox::sorry( 0,
+ i18n("You have specified invalid argument (\"%1\") for \"type\" command-line option.")
+ .arg(fileType));
+ return false;
+ }
+
+// if (cdata.driverName.isEmpty())
+// cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
+ if (!args->getOption("host").isEmpty())
+ cdata.hostName = args->getOption("host");
+ if (!args->getOption("local-socket").isEmpty())
+ cdata.localSocketFileName = args->getOption("local-socket");
+ if (!args->getOption("user").isEmpty())
+ cdata.userName = args->getOption("user");
+// cdata.password = args->getOption("password");
+ bool fileDriverSelected;
+ if (cdata.driverName.isEmpty())
+ fileDriverSelected = true;
+ else {
+ KexiDB::DriverManager dm;
+ KexiDB::Driver::Info dinfo = dm.driverInfo(cdata.driverName);
+ if (dinfo.name.isEmpty()) {
+ //driver name provided explicitly, but not found
+ KMessageBox::sorry(0, dm.errorMsg());
+ return false;
+ }
+ fileDriverSelected = dinfo.fileBased;
+ }
+ bool projectFileExists = false;
+
+ //obfuscate the password, if present
+//removed
+/*
+ for (int i=1; i<(argc-1); i++) {
+ if (qstrcmp("--password",argv[i])==0
+ || qstrcmp("-password",argv[i])==0)
+ {
+ QCString pwd(argv[i+1]);
+ if (!pwd.isEmpty()) {
+ pwd.fill(' ');
+ pwd[0]='x';
+ qstrcpy(argv[i+1], (const char*)pwd);
+ }
+ break;
+ }
+ }
+ */
+
+ const QString portStr = args->getOption("port");
+ if (!portStr.isEmpty()) {
+ bool ok;
+ const int p = portStr.toInt(&ok);
+ if (ok && p > 0)
+ cdata.port = p;
+ else {
+ KMessageBox::sorry( 0,
+ i18n("You have specified invalid port number \"%1\"."));
+ return false;
+ }
+ }
+
+ m_forcedUserMode = args->isSet("user-mode");
+ m_forcedDesignMode = args->isSet("design-mode");
+ m_isProjectNavigatorVisible = args->isSet("show-navigator");
+ bool createDB = args->isSet("createdb");
+ const bool alsoOpenDB = args->isSet("create-opendb");
+ if (alsoOpenDB)
+ createDB = true;
+ const bool dropDB = args->isSet("dropdb");
+ const bool openExisting = !createDB && !dropDB;
+ const bool readOnly = args->isSet("readonly");
+ const QString couldnotMsg = QString::fromLatin1("\n")
+ +i18n("Could not start Kexi application this way.");
+
+ if (createDB && dropDB) {
+ KMessageBox::sorry( 0, i18n(
+ "You have used both \"createdb\" and \"dropdb\" startup options.")+couldnotMsg);
+ return false;
+ };
+
+ if (createDB || dropDB) {
+ if (args->count()<1) {
+ KMessageBox::sorry( 0, i18n("No project name specified.") );
+ return false;
+ }
+ m_action = Exit;
+ }
+
+//TODO: add option for non-gui; integrate with KWallet;
+// move to static KexiProject method
+ if (!fileDriverSelected && !cdata.driverName.isEmpty() && cdata.password.isEmpty()) {
+
+ if (cdata.password.isEmpty()) {
+ delete d->passwordDialog;
+ d->passwordDialog = new KexiDBPasswordDialog(0, cdata, true);
+// connect( d->passwordDialog, SIGNAL(user1Clicked()),
+// this, SLOT(slotShowConnectionDetails()) );
+ const int ret = d->passwordDialog->exec();
+ if (d->passwordDialog->showConnectionDetailsRequested() || ret == QDialog::Accepted) {
+// if ( ret == QDialog::Accepted ) {
+ // if (QDialog::Accepted == KPasswordDialog::getPassword(pwd, msg)) {
+//moved cdata.password = QString(pwd);
+// }
+ } else {
+ m_action = Exit;
+ return true;
+ }
+ }
+ }
+
+/* kdDebug() << "ARGC==" << args->count() << endl;
+ for (int i=0;i<args->count();i++) {
+ kdDebug() << "ARG" <<i<< "= " << args->arg(i) <<endl;
+ }*/
+
+ if (m_forcedUserMode && m_forcedDesignMode) {
+ KMessageBox::sorry( 0, i18n(
+ "You have used both \"user-mode\" and \"design-mode\" startup options.")+couldnotMsg);
+ return false;
+ }
+
+ //database filenames, shortcut filenames or db names on a server
+ if (args->count()>=1) {
+ QString prjName;
+ QString fileName;
+ if (fileDriverSelected) {
+ fileName = QFile::decodeName(args->arg(0));
+ }
+ else {
+ prjName = QString::fromLocal8Bit(args->arg(0));
+ }
+
+ if (fileDriverSelected) {
+ QFileInfo finfo(fileName);
+ prjName = finfo.fileName(); //filename only, to avoid messy names like when Kexi is started with "../../db" arg
+ cdata.setFileName( finfo.absFilePath() );
+ projectFileExists = finfo.exists();
+
+ if (dropDB && !projectFileExists) {
+ KMessageBox::sorry(0,
+ i18n("Could not remove project.\nThe file \"%1\" does not exist.")
+ .arg(QDir::convertSeparators(cdata.dbFileName())));
+ return 0;
+ }
+ }
+
+ if (createDB) {
+ if (cdata.driverName.isEmpty())
+ cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
+ m_projectData = new KexiProjectData(cdata, prjName); //dummy
+ }
+ else {
+ if (fileDriverSelected) {
+ int detectOptions = 0;
+ if (fileType=="project")
+ detectOptions |= ThisIsAProjectFile;
+ else if (fileType=="shortcut")
+ detectOptions |= ThisIsAShortcutToAProjectFile;
+ else if (fileType=="connection")
+ detectOptions |= ThisIsAShortcutToAConnectionData;
+
+ if (dropDB)
+ detectOptions |= DontConvert;
+
+ QString detectedDriverName;
+ const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
+ cdata.driverName, cdata.fileName(), 0, detectOptions );
+ if (true != res)
+ return res;
+
+ if (m_importActionData) { //importing action
+ m_action = ImportProject;
+ return true;
+ }
+
+ //opening action
+ cdata.driverName = detectedDriverName;
+ if (cdata.driverName=="shortcut") {
+ //get information for a shortcut file
+ d->shortcutFile = new KexiDBShortcutFile(cdata.fileName());
+ m_projectData = new KexiProjectData();
+ if (!d->shortcutFile->loadProjectData(*m_projectData, &d->shortcutFileGroupKey)) {
+ KMessageBox::sorry(0, i18n("Could not open shortcut file\n\"%1\".")
+ .arg(QDir::convertSeparators(cdata.fileName())));
+ delete m_projectData;
+ m_projectData = 0;
+ delete d->shortcutFile;
+ d->shortcutFile = 0;
+ return false;
+ }
+ d->connDialog = new KexiDBConnectionDialog(
+ *m_projectData, d->shortcutFile->fileName());
+ connect(d->connDialog, SIGNAL(saveChanges()),
+ this, SLOT(slotSaveShortcutFileChanges()));
+ int res = d->connDialog->exec();
+ if (res == QDialog::Accepted) {
+ //get (possibly changed) prj data
+ *m_projectData = d->connDialog->currentProjectData();
+ }
+
+ delete d->connDialog;
+ d->connDialog = 0;
+ delete d->shortcutFile;
+ d->shortcutFile = 0;
+
+ if (res == QDialog::Rejected) {
+ delete m_projectData;
+ m_projectData = 0;
+ return cancelled;
+ }
+ }
+ else if (cdata.driverName=="connection") {
+ //get information for a connection file
+ d->connShortcutFile = new KexiDBConnShortcutFile(cdata.fileName());
+ if (!d->connShortcutFile->loadConnectionData(cdata, &d->shortcutFileGroupKey)) {
+ KMessageBox::sorry(0, i18n("Could not open connection data file\n\"%1\".")
+ .arg(QDir::convertSeparators(cdata.fileName())));
+ delete d->connShortcutFile;
+ d->connShortcutFile = 0;
+ return false;
+ }
+ bool cancel = false;
+ const bool showConnectionDialog = !args->isSet("skip-conn-dialog");
+ while (true) {
+ if (showConnectionDialog) {
+ //show connection dialog, so user can change parameters
+ if (!d->connDialog) {
+ d->connDialog = new KexiDBConnectionDialog(
+ cdata, d->connShortcutFile->fileName());
+ connect(d->connDialog, SIGNAL(saveChanges()),
+ this, SLOT(slotSaveShortcutFileChanges()));
+ }
+ const int res = d->connDialog->exec();
+ if (res == QDialog::Accepted) {
+ //get (possibly changed) prj data
+ cdata = *d->connDialog->currentProjectData().constConnectionData();
+ }
+ else {
+ cancel = true;
+ break;
+ }
+ }
+ m_projectData = selectProject(&cdata, cancel);
+ if (m_projectData || cancel || !showConnectionDialog)
+ break;
+ }
+
+ delete d->connShortcutFile;
+ d->connShortcutFile = 0;
+ delete d->connDialog;
+ d->connDialog = 0;
+
+ if (cancel)
+ return cancelled;
+ }
+ else
+ m_projectData = new KexiProjectData(cdata, prjName);
+ }
+ else
+ m_projectData = new KexiProjectData(cdata, prjName);
+
+ }
+// if (!m_projectData)
+// return false;
+ }
+ if (args->count()>1) {
+ //TODO: KRun another Kexi instances
+ }
+
+ //let's show connection details, user asked for that in the "password dialog"
+ if (d->passwordDialog && d->passwordDialog->showConnectionDetailsRequested()) {
+ d->connDialog = new KexiDBConnectionDialog(*m_projectData);
+// connect(d->connDialog->tabWidget->mainWidget, SIGNAL(saveChanges()),
+// this, SLOT(slotSaveShortcutFileChanges()));
+ int res = d->connDialog->exec();
+
+ if (res == QDialog::Accepted) {
+ //get (possibly changed) prj data
+ *m_projectData = d->connDialog->currentProjectData();
+ }
+
+ delete d->connDialog;
+ d->connDialog = 0;
+
+ if (res == QDialog::Rejected) {
+ delete m_projectData;
+ m_projectData = 0;
+ return cancelled;
+ }
+ }
+
+ //---autoopen objects:
+ const bool atLeastOneAOOFound = getAutoopenObjects(args, "open")
+ || getAutoopenObjects(args, "design")
+ || getAutoopenObjects(args, "edittext")
+ || getAutoopenObjects(args, "execute")
+ || getAutoopenObjects(args, "new")
+ || getAutoopenObjects(args, "print")
+ || getAutoopenObjects(args, "print-preview");
+
+ if (atLeastOneAOOFound && !openExisting) {
+ KMessageBox::information( 0,
+ i18n("You have specified a few database objects to be opened automatically, "
+ "using startup options.\n"
+ "These options will be ignored because it is not available while creating "
+ "or dropping projects."));
+ }
+
+ if (createDB) {
+ bool creationNancelled;
+ KexiGUIMessageHandler gui;
+ KexiProject *prj = KexiProject::createBlankProject(creationNancelled, projectData(), &gui);
+ bool ok = prj!=0;
+ delete prj;
+ if (creationNancelled)
+ return cancelled;
+ if (!alsoOpenDB) {
+ if (ok) {
+ KMessageBox::information( 0, i18n("Project \"%1\" created successfully.")
+ .arg( QDir::convertSeparators(projectData()->databaseName()) ));
+ }
+ return ok;
+ }
+ }
+ else if (dropDB) {
+ KexiGUIMessageHandler gui;
+ tristate res = KexiProject::dropProject(projectData(), &gui, false/*ask*/);
+ if (res==true)
+ KMessageBox::information( 0, i18n("Project \"%1\" dropped successfully.")
+ .arg( QDir::convertSeparators(projectData()->databaseName()) ));
+ return res!=false;
+ }
+
+ //------
+
+/* if (m_forcedFinalMode || (m_projectData && projectData->finalMode())) {
+ //TODO: maybe also auto allow to open objects...
+ KexiMainWindowImpl::initFinal(m_projectData);
+ return;
+ }*/
+
+ if (!m_projectData) {
+ cdata = KexiDB::ConnectionData(); //clear
+
+ if (args->isSet("skip-startup-dialog") || !KexiStartupDialog::shouldBeShown())
+ return true;
+
+ if (!d->startupDialog) {
+ //create d->startupDialog for reuse because it can be used again after conn err.
+ d->startupDialog = new KexiStartupDialog(
+ KexiStartupDialog::Everything, KexiStartupDialog::CheckBoxDoNotShowAgain,
+ Kexi::connset(), Kexi::recentProjects(), 0, "KexiStartupDialog");
+ }
+ if (d->startupDialog->exec()!=QDialog::Accepted)
+ return true;
+
+ const int r = d->startupDialog->result();
+ if (r == KexiStartupDialog::CreateBlankResult) {
+ m_action = CreateBlankProject;
+ return true;
+ }
+ else if (r == KexiStartupDialog::ImportResult) {
+ m_action = ImportProject;
+ return true;
+ }
+ else if (r == KexiStartupDialog::CreateFromTemplateResult) {
+ const QString selFile( d->startupDialog->selectedFileName() );
+ cdata.setFileName( selFile );
+ QString detectedDriverName;
+ const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
+ cdata.driverName, selFile );
+ if (true != res)
+ return res;
+ if (m_importActionData || detectedDriverName.isEmpty())
+ return false;
+ cdata.driverName = detectedDriverName;
+ m_projectData = new KexiProjectData(cdata, selFile);
+ m_projectData->autoopenObjects = d->startupDialog->autoopenObjects();
+ m_action = CreateFromTemplate;
+ return true;
+ }
+ else if (r == KexiStartupDialog::OpenExistingResult) {
+// kdDebug() << "Existing project --------" << endl;
+ const QString selFile( d->startupDialog->selectedFileName() );
+ if (!selFile.isEmpty()) {
+ //file-based project
+// kdDebug() << "Project File: " << selFile << endl;
+ cdata.setFileName( selFile );
+ QString detectedDriverName;
+ const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
+ cdata.driverName, selFile );
+ if (true != res)
+ return res;
+ if (m_importActionData) { //importing action
+ m_action = ImportProject;
+ return true;
+ }
+
+ if (detectedDriverName.isEmpty())
+ return false;
+ cdata.driverName = detectedDriverName;
+ m_projectData = new KexiProjectData(cdata, selFile);
+ }
+ else if (d->startupDialog->selectedExistingConnection()) {
+// kdDebug() << "Existing connection: " <<
+// d->startupDialog->selectedExistingConnection()->serverInfoString() << endl;
+ KexiDB::ConnectionData *cdata = d->startupDialog->selectedExistingConnection();
+ //ok, now we will try to show projects for this connection to the user
+ bool cancelled;
+ m_projectData = selectProject( cdata, cancelled );
+ if (!m_projectData && !cancelled || cancelled) {
+ //try again
+ return init(0, 0);
+ }
+ //not needed anymore
+ delete d->startupDialog;
+ d->startupDialog = 0;
+ }
+ }
+ else if (r==KexiStartupDialog::OpenRecentResult) {
+// kdDebug() << "Recent project --------" << endl;
+ const KexiProjectData *data = d->startupDialog->selectedProjectData();
+ if (data) {
+// kdDebug() << "Selected project: database=" << data->databaseName()
+// << " connection=" << data->constConnectionData()->serverInfoString() << endl;
+ }
+//! @todo
+ return data!=0;
+ }
+
+ if (!m_projectData)
+ return true;
+ }
+
+ if (m_projectData && (openExisting || (createDB && alsoOpenDB))) {
+ m_projectData->setReadOnly( readOnly );
+ m_action = OpenProject;
+ }
+ //show if wasn't show yet
+// importantInfo(true);
+
+ return true;
+}
+
+tristate KexiStartupHandler::detectActionForFile(
+ KexiStartupData::Import& detectedImportAction, QString& detectedDriverName,
+ const QString& _suggestedDriverName, const QString &dbFileName, QWidget *parent, int options )
+{
+ detectedImportAction = KexiStartupData::Import(); //clear
+ QString suggestedDriverName(_suggestedDriverName); //safe
+ detectedDriverName = QString::null;
+ QFileInfo finfo(dbFileName);
+ if (dbFileName.isEmpty() || !finfo.isReadable()) {
+ if (!(options & SkipMessages))
+ KMessageBox::sorry(parent, i18n("<p>Could not open project.</p>")
+ +i18n("<p>The file <nobr>\"%1\"</nobr> does not exist or is not readable.</p>")
+ .arg(QDir::convertSeparators(dbFileName))
+ +i18n("Check the file's permissions and whether it is already opened "
+ "and locked by another application."));
+ return false;
+ }
+
+ KMimeType::Ptr ptr;
+ QString mimename;
+
+ const bool thisIsShortcut = (options & ThisIsAShortcutToAProjectFile)
+ || (options & ThisIsAShortcutToAConnectionData);
+
+ if ((options & ThisIsAProjectFile) || !thisIsShortcut) {
+ //try this detection if "project file" mode is forced or no type is forced:
+ ptr = KMimeType::findByFileContent(dbFileName);
+ mimename = ptr.data()->name();
+ kdDebug() << "KexiStartupHandler::detectActionForFile(): found mime is: "
+ << mimename << endl;
+ if (mimename.isEmpty() || mimename=="application/octet-stream" || mimename=="text/plain") {
+ //try by URL:
+ ptr = KMimeType::findByURL(dbFileName);
+ mimename = ptr.data()->name();
+ }
+ }
+ if (mimename.isEmpty() || mimename=="application/octet-stream") {
+ // perhaps the file is locked
+ QFile f(dbFileName);
+ if (!f.open(IO_ReadOnly)) {
+ // BTW: similar error msg is provided in SQLiteConnection::drv_useDatabase()
+ if (!(options & SkipMessages))
+ KMessageBox::sorry(parent, i18n("<p>Could not open project.</p>")
+ +i18n("<p>The file <nobr>\"%1\"</nobr> is not readable.</p>")
+ .arg(QDir::convertSeparators(dbFileName))
+ +i18n("Check the file's permissions and whether it is already opened "
+ "and locked by another application."));
+ return false;
+ }
+ }
+ if ((options & ThisIsAShortcutToAProjectFile) || mimename=="application/x-kexiproject-shortcut") {
+ detectedDriverName = "shortcut";
+ return true;
+ }
+
+ if ((options & ThisIsAShortcutToAConnectionData) || mimename=="application/x-kexi-connectiondata") {
+ detectedDriverName = "connection";
+ return true;
+ }
+
+ //! @todo rather check this using migration drivers'
+ //! X-KexiSupportedMimeTypes [strlist] property
+ if (ptr.data()) {
+ if (mimename=="application/x-msaccess") {
+ if ((options & SkipMessages) || KMessageBox::Yes != KMessageBox::questionYesNo(
+ parent, i18n("\"%1\" is an external file of type:\n\"%2\".\n"
+ "Do you want to import the file as a Kexi project?")
+ .arg(QDir::convertSeparators(dbFileName)).arg(ptr.data()->comment()),
+ i18n("Open External File"), KGuiItem(i18n("Import...")), KStdGuiItem::cancel() ) )
+ {
+ return cancelled;
+ }
+ detectedImportAction.mimeType = mimename;
+ detectedImportAction.fileName = dbFileName;
+ return true;
+ }
+ }
+
+ if (!finfo.isWritable()) {
+ //! @todo if file is ro: change project mode (but do not care if we're jsut importing)
+ }
+
+ // "application/x-kexiproject-sqlite", etc.:
+ QString tmpDriverName = Kexi::driverManager().lookupByMime(mimename).latin1();
+//@todo What about trying to reuse KOFFICE FILTER CHAINS here?
+ bool useDetectedDriver = suggestedDriverName.isEmpty() || suggestedDriverName.lower()==detectedDriverName.lower();
+ if (!useDetectedDriver) {
+ int res = KMessageBox::Yes;
+ if (!(options & SkipMessages))
+ res = KMessageBox::warningYesNoCancel(parent, i18n(
+ "The project file \"%1\" is recognized as compatible with \"%2\" database driver, "
+ "while you have asked for \"%3\" database driver to be used.\n"
+ "Do you want to use \"%4\" database driver?")
+ .arg(QDir::convertSeparators(dbFileName))
+ .arg(tmpDriverName).arg(suggestedDriverName).arg(tmpDriverName));
+ if (KMessageBox::Yes == res)
+ useDetectedDriver = true;
+ else if (KMessageBox::Cancel == res)
+ return cancelled;
+ }
+ if (useDetectedDriver) {
+ detectedDriverName = tmpDriverName;
+ }
+ else {//use suggested driver
+ detectedDriverName = suggestedDriverName;
+ }
+// kdDebug() << "KexiStartupHandler::detectActionForFile(): driver name: " << detectedDriverName << endl;
+//hardcoded for convenience:
+ const QString newFileFormat = "SQLite3";
+ if (!(options & DontConvert || options & SkipMessages)
+ && detectedDriverName.lower()=="sqlite2" && detectedDriverName.lower()!=suggestedDriverName.lower()
+ && KMessageBox::Yes == KMessageBox::questionYesNo(parent, i18n(
+ "Previous version of database file format (\"%1\") is detected in the \"%2\" "
+ "project file.\nDo you want to convert the project to a new \"%3\" format (recommended)?")
+ .arg(detectedDriverName).arg(QDir::convertSeparators(dbFileName)).arg(newFileFormat)) )
+ {
+// SQLite2ToSQLite3Migration *migr = new
+ SQLite2ToSQLite3Migration migr( finfo.absFilePath() );
+ tristate res = migr.run();
+// kdDebug() << "--- migr.run() END ---" <<endl;
+ if (!res) {
+ //TODO msg
+ KMessageBox::sorry(parent, i18n(
+ "Failed to convert project file \"%1\" to a new \"%2\" format.\n"
+ "The file format remains unchanged.")
+ .arg(QDir::convertSeparators(dbFileName)).arg(newFileFormat) );
+ //continue...
+ }
+ if (res==true)
+ detectedDriverName = newFileFormat;
+ }
+// action.driverName = detectedDriverName;
+ if (detectedDriverName.isEmpty()) {
+ QString possibleProblemsInfoMsg( Kexi::driverManager().possibleProblemsInfoMsg() );
+ if (!possibleProblemsInfoMsg.isEmpty()) {
+ possibleProblemsInfoMsg.prepend(QString::fromLatin1("<p>")+i18n("Possible problems:"));
+ possibleProblemsInfoMsg += QString::fromLatin1("</p>");
+ }
+ if (!(options & SkipMessages))
+ KMessageBox::detailedSorry(parent,
+ i18n( "The file \"%1\" is not recognized as being supported by Kexi.")
+ .arg(QDir::convertSeparators(dbFileName)),
+ QString::fromLatin1("<p>")
+ +i18n("Database driver for this file type not found.\nDetected MIME type: %1")
+ .arg(mimename)
+ +(ptr.data()->comment().isEmpty()
+ ? QString::fromLatin1(".") : QString::fromLatin1(" (%1).").arg(ptr.data()->comment()))
+ +QString::fromLatin1("</p>")
+ +possibleProblemsInfoMsg);
+ return false;
+ }
+ return true;
+}
+
+KexiProjectData*
+KexiStartupHandler::selectProject(KexiDB::ConnectionData *cdata, bool& cancelled, QWidget *parent)
+{
+ clearStatus();
+ cancelled = false;
+ if (!cdata)
+ return 0;
+ if (!cdata->savePassword && cdata->password.isEmpty()) {
+ if (!d->passwordDialog)
+ d->passwordDialog = new KexiDBPasswordDialog(0, *cdata, false);
+ const int ret = d->passwordDialog->exec();
+ if (d->passwordDialog->showConnectionDetailsRequested() || ret == QDialog::Accepted) {
+
+ } else {
+ cancelled = true;
+ return 0;
+ }
+ }
+ KexiProjectData* projectData = 0;
+ //dialog for selecting a project
+ KexiProjectSelectorDialog prjdlg( parent, "prjdlg", cdata, true, false );
+ if (!prjdlg.projectSet() || prjdlg.projectSet()->error()) {
+ KexiGUIMessageHandler msgh;
+ if (prjdlg.projectSet())
+ msgh.showErrorMessage(prjdlg.projectSet(),
+ i18n("Could not load list of available projects for <b>%1</b> database server.")
+ .arg(cdata->serverInfoString(true)));
+ else
+ msgh.showErrorMessage(
+ i18n("Could not load list of available projects for <b>%1</b> database server.")
+ .arg(cdata->serverInfoString(true)));
+// setStatus(i18n("Could not load list of available projects for database server \"%1\"")
+// .arg(cdata->serverInfoString(true)), prjdlg.projectSet()->errorMsg());
+ return 0;
+ }
+ if (prjdlg.exec()!=QDialog::Accepted) {
+ cancelled = true;
+ return 0;
+ }
+ if (prjdlg.selectedProjectData()) {
+ //deep copy
+ projectData = new KexiProjectData(*prjdlg.selectedProjectData());
+ }
+ return projectData;
+}
+
+void KexiStartupHandler::slotSaveShortcutFileChanges()
+{
+ bool ok = true;
+ if (d->shortcutFile)
+ ok = d->shortcutFile->saveProjectData(d->connDialog->currentProjectData(),
+ d->connDialog->savePasswordOptionSelected(),
+ &d->shortcutFileGroupKey );
+ else if (d->connShortcutFile)
+ ok = d->connShortcutFile->saveConnectionData(
+ *d->connDialog->currentProjectData().connectionData(),
+ d->connDialog->savePasswordOptionSelected(),
+ &d->shortcutFileGroupKey );
+
+ if (!ok) {
+ KMessageBox::sorry(0, i18n("Failed saving connection data to\n\"%1\" file.")
+ .arg(QDir::convertSeparators(d->shortcutFile->fileName())));
+ }
+}
+
+/*void KexiStartupHandler::slotShowConnectionDetails()
+{
+ d->passwordDialog->close();
+ d->showConnectionDetailsExecuted = true;
+}*/
+
+#include "KexiStartup.moc"
diff --git a/kexi/main/startup/KexiStartup.h b/kexi/main/startup/KexiStartup.h
new file mode 100644
index 00000000..294ad7dd
--- /dev/null
+++ b/kexi/main/startup/KexiStartup.h
@@ -0,0 +1,136 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXI_STARTUPHANDLER_H
+#define KEXI_STARTUPHANDLER_H
+
+#include <qstring.h>
+#include <qwidget.h>
+#include <kpassdlg.h>
+
+#include <core/kexistartupdata.h>
+#include <core/kexi.h>
+#include <kexiutils/tristate.h>
+
+class KexiProjectData;
+class KexiProjectData;
+class KCmdLineArgs;
+class KexiStartupHandlerPrivate;
+namespace KexiDB {
+ class ConnectionData;
+}
+
+/*! */
+class KEXIMAIN_EXPORT KexiDBPasswordDialog : public KPasswordDialog
+{
+ Q_OBJECT
+ public:
+ KexiDBPasswordDialog(QWidget *parent, KexiDB::ConnectionData& cdata, bool showDetailsButton = false);
+ virtual ~KexiDBPasswordDialog();
+
+ bool showConnectionDetailsRequested() const { return m_showConnectionDetailsRequested; }
+
+ protected slots:
+ virtual void done(int r);
+ void slotShowConnectionDetails();
+
+ protected:
+ KexiDB::ConnectionData *m_cdata;
+ bool m_showConnectionDetailsRequested : 1;
+};
+
+/*! Handles startup actions for Kexi application.
+*/
+class KEXIMAIN_EXPORT KexiStartupHandler
+ : public QObject, public KexiStartupData, public Kexi::ObjectStatus
+{
+ Q_OBJECT
+
+ public:
+ KexiStartupHandler();
+ virtual ~KexiStartupHandler();
+
+ virtual tristate init(int argc, char **argv);
+
+ #if 0
+ /*! Used for opening existing projects.
+ Detects project file type by mime type and returns project data, if it can be detected,
+ otherwise - NULL. \a parent is passed as parent for potential error message boxes.
+ Also uses \a cdata connection data for server-based projects.
+ cdata.driverName is adjusted, if a file-based project has been detected.
+ */
+ static KexiProjectData* detectProjectData(
+ KexiDB::ConnectionData& cdata, const QString &dbname, QWidget *parent);
+ #endif
+
+ /*! Options for detectDriverForFile() */
+ enum DetectDriverForFileOptions {
+ DontConvert = 1, //!< skip asking for conversion (used e.g. when dropdb is called)
+ ThisIsAProjectFile = 2, //!< a hint, forces detection of the file as a project file
+ ThisIsAShortcutToAProjectFile = 4, //!< a hint, forces detection of the file
+ //!< as a shortcut to a project file
+ ThisIsAShortcutToAConnectionData = 8, //!< a hint, forces detection of the file
+ //!< as a shortcut to a connection data
+ SkipMessages = 16 //!< do not display error or warning messages
+ };
+
+ /*! Used for opening existing file-based projects.
+ Detects actions that should be performed for by looking at the file's mime type.
+ \return true if actions should be performed or cancelled if action should be cancelled
+ In this case there are two possibilities:
+ - \a detectedImportAction == true means "import action" should be performed
+ - nonempty \a detectedDriverName means "open action" should be performed.
+
+ \a detectedDriverName can contain following special strings:
+ - "shortcut" if the file looks like a shortcut to a project/connection file
+ - "connection" if the file looks like a connection data file.
+
+ \a parent is passed as a parent for potential error message boxes.
+ \a driverName is a preferred driver name.
+ \a options should be a combination of DetectDriverForFileOptions enum values. */
+ static tristate detectActionForFile(
+ KexiStartupData::Import& detectedImportAction, QString& detectedDriverName,
+ const QString& _suggestedDriverName,
+ const QString &dbFileName, QWidget *parent = 0, int options = 0 );
+
+ /*! Allows user to select a project with KexiProjectSelectorDialog.
+ \return selected project's data
+ Returns NULL and sets cancelled to true if the dialog was cancelled.
+ Returns NULL and sets cancelled to false if there was an error.
+ */
+ KexiProjectData* selectProject(KexiDB::ConnectionData *cdata, bool& cancelled, QWidget *parent = 0);
+
+ protected slots:
+ void slotSaveShortcutFileChanges();
+// void slotShowConnectionDetails();
+
+ protected:
+ bool getAutoopenObjects(KCmdLineArgs *args, const QCString &action_name);
+
+ KexiStartupHandlerPrivate *d;
+};
+
+namespace Kexi
+{
+ //! \return singleton Startup Handler singleton.
+ KEXIMAIN_EXPORT KexiStartupHandler& startupHandler();
+}
+
+#endif
+
diff --git a/kexi/main/startup/KexiStartupDialog.cpp b/kexi/main/startup/KexiStartupDialog.cpp
new file mode 100644
index 00000000..3b524492
--- /dev/null
+++ b/kexi/main/startup/KexiStartupDialog.cpp
@@ -0,0 +1,699 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiStartupDialog.h"
+#include "KexiStartupDialogTemplatesPage.h"
+#include "kexi.h"
+#include "KexiProjectSelector.h"
+#include "KexiOpenExistingFile.h"
+#include "KexiConnSelector.h"
+#include "KexiConnSelectorBase.h"
+
+#include <qlayout.h>
+#include <qtabwidget.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qpoint.h>
+#include <qobjectlist.h>
+#include <qvgroupbox.h>
+#include <qapplication.h>
+#include <qtooltip.h>
+#include <qwidgetstack.h>
+
+#include <klocale.h>
+#include <kdeversion.h>
+#include <kinstance.h>
+#include <kdebug.h>
+#include <kpushbutton.h>
+#include <kjanuswidget.h>
+#include <kglobalsettings.h>
+#include <ktextedit.h>
+#include <kfileiconview.h>
+#include <kfileitem.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kmimetype.h>
+#include <ktextbrowser.h>
+#include <kconfig.h>
+
+#ifdef KEXI_SHOW_UNIMPLEMENTED
+#define KEXI_STARTUP_SHOW_TEMPLATES
+#define KEXI_STARTUP_SHOW_RECENT
+#endif
+
+//! @internal
+class KexiStartupDialogPrivate {
+public:
+ KexiStartupDialogPrivate()
+ : pageTemplates(0), pageOpenExisting(0), pageOpenRecent(0)
+ , pageTemplatesID(-1)
+ , pageOpenExistingID(-1)
+ , pageOpenRecentID(-1)
+ {
+ result = 0;
+ QString none, iconname;
+ iconname = KMimeType::mimeType( KexiDB::Driver::defaultFileBasedDriverMimeType() )->icon(none,0);
+ kexi_sqlite_icon = KGlobal::iconLoader()->loadIcon( iconname, KIcon::Desktop );
+ iconname = KMimeType::mimeType("application/x-kexiproject-shortcut")->icon(none,0);
+ kexi_shortcut_icon = KGlobal::iconLoader()->loadIcon( iconname, KIcon::Desktop );
+ prj_selector = 0;
+ chkDoNotShow = 0;
+ openExistingConnWidget = 0;
+ templatesWidget = 0;
+ templatesWidget_IconListBox = 0;
+ }
+ ~KexiStartupDialogPrivate()
+ {}
+
+ int dialogType, dialogOptions;
+
+ QFrame *pageTemplates, *pageOpenExisting, *pageOpenRecent;
+ int pageTemplatesID;
+ int pageOpenExistingID, pageOpenRecentID;
+ int templatesSectionID_blank, templatesSectionID_import;
+#ifdef DB_TEMPLATES
+ int templatesSectionID_templates; //, templatesSectionID_custom2;
+#endif
+ QCheckBox *chkDoNotShow;
+
+ //widgets for template tab:
+ KJanusWidget* templatesWidget;
+ QObject *templatesWidget_IconListBox;//helper
+
+ QWidgetStack *viewBlankTempl;
+ KexiStartupDialogTemplatesPage *viewTemplates;
+ //TemplatesPage *viewBusinessTempl;
+
+ int result;
+
+ QPixmap kexi_sqlite_icon, kexi_shortcut_icon;
+
+// //! Key string of selected database template. \sa selectedTemplateKey()
+// QString selectedTemplateKey;
+
+ //! used for "open existing"
+ KexiDBConnectionSet *connSet;
+ KexiStartupFileDialog *openExistingFileDlg; //! embedded file dialog
+ KexiConnSelectorWidget *openExistingConnWidget;
+ QString existingFileToOpen; //! helper for returning a file name to open
+ KexiDB::ConnectionData* selectedExistingConnection; //! helper for returning selected connection
+
+ //! used for "open recent"
+ KexiProjectSet *recentProjects;
+ KexiProjectSelectorWidget* prj_selector;
+
+ //! true if the dialog contain single page, not tabs
+ bool singlePage : 1;
+};
+
+bool dlgSinglePage(int type)
+{
+ return (type==KexiStartupDialog::Templates)
+ || (type==KexiStartupDialog::OpenExisting)
+ || (type==KexiStartupDialog::OpenRecent);
+}
+
+QString captionForDialogType(int type)
+{
+ if (type==KexiStartupDialog::Templates)
+ return i18n("Create Project");
+ else if (type==KexiStartupDialog::OpenExisting)
+ return i18n("Open Existing Project");
+ else if (type==KexiStartupDialog::OpenRecent)
+ return i18n("Open Recent Project");
+
+ return i18n("Choose Project");
+}
+
+/*================================================================*/
+/*KexiStartupDialog::KexiStartupDialog(QWidget *parent, const char *name, KInstance* global,
+ const QCString &format, const QString &nativePattern,
+ const QString &nativeName, const DialogType &dialogType,
+ const QCString& templateType) :
+ KDialogBase(parent, name, true, i18n("Open Document"), KDialogBase::Ok | KDialogBase::Cancel,
+ KDialogBase::Ok) {
+*/
+KexiStartupDialog::KexiStartupDialog(
+ int dialogType, int dialogOptions,
+ KexiDBConnectionSet& connSet, KexiProjectSet& recentProjects,
+ QWidget *parent, const char *name )
+ : KDialogBase(
+ dlgSinglePage(dialogType) ? Plain : Tabbed
+ ,captionForDialogType(dialogType)
+ ,Help | Ok | Cancel, Ok, parent, name )
+ , d(new KexiStartupDialogPrivate())
+{
+ d->recentProjects = &recentProjects;
+ d->connSet = &connSet;
+ d->dialogType = dialogType;
+ d->dialogOptions = dialogOptions;
+ d->singlePage = dlgSinglePage(dialogType);
+
+ if (dialogType==OpenExisting) {//this dialog has "open" tab only!
+ setIcon(DesktopIcon("fileopen"));
+ } else {
+ setIcon(d->kexi_sqlite_icon);
+ }
+
+ setSizeGripEnabled(true);
+ int id=0;
+ if (d->dialogType & Templates) {
+ setupPageTemplates();
+ d->pageTemplatesID = id++;
+ d->templatesWidget->setFocus();
+ }
+ if (d->dialogType & OpenExisting) {
+ setupPageOpenExisting();
+ d->pageOpenExistingID = id++;
+ if (d->singlePage)
+ d->openExistingConnWidget->setFocus();
+ }
+#ifdef KEXI_STARTUP_SHOW_RECENT
+ if (d->dialogType & OpenRecent) {
+ setupPageOpenRecent();
+ d->pageOpenRecentID = id++;
+ if (d->singlePage)
+ d->prj_selector->setFocus();
+ }
+#endif
+
+ if (!d->singlePage) {
+ connect(this, SIGNAL(aboutToShowPage(QWidget*)), this, SLOT(slotPageShown(QWidget*)));
+ d->templatesWidget->setFocus();
+ }
+ showPage(0);
+ adjustSize();
+}
+
+KexiStartupDialog::~KexiStartupDialog()
+{
+ delete d;
+}
+
+bool KexiStartupDialog::shouldBeShown()
+{
+ KGlobal::config()->setGroup("Startup");
+ return KGlobal::config()->readBoolEntry("ShowStartupDialog",true);
+}
+
+void KexiStartupDialog::show()
+{
+ //just some cleanup
+// d->selectedTemplateKey=QString::null;
+ d->existingFileToOpen=QString::null;
+ d->result=-1;
+
+ KDialog::centerOnScreen(this);
+ KDialogBase::show();
+}
+
+int KexiStartupDialog::result() const
+{
+ return d->result;
+}
+
+void KexiStartupDialog::done(int r)
+{
+ if (d->result!=-1) //already done!
+ return;
+
+// kdDebug() << "KexiStartupDialog::done(" << r << ")" << endl;
+// updateSelectedTemplateKeyInfo();
+
+ if (r==QDialog::Rejected) {
+ d->result = CancelResult;
+ } else {
+ const int idx = activePageIndex();
+ if (idx == d->pageTemplatesID) {
+ const int templateIdx = d->templatesWidget->activePageIndex();
+ if (templateIdx == d->templatesSectionID_blank)
+ d->result = CreateBlankResult;
+#ifdef DB_TEMPLATES
+ else if (templateIdx == d->templatesSectionID_templates)
+ d->result = CreateFromTemplateResult;
+#endif
+ else if (templateIdx == d->templatesSectionID_import)
+ d->result = ImportResult;
+ }
+ else if (idx == d->pageOpenExistingID) {
+ // return file or connection:
+ if (d->openExistingConnWidget->selectedConnectionType()==KexiConnSelectorWidget::FileBased) {
+ if (!d->openExistingFileDlg->checkFileName())
+ return;
+ d->existingFileToOpen = d->openExistingFileDlg->currentFileName();
+// d->existingFileToOpen = d->openExistingFileDlg->currentURL().path();
+ d->selectedExistingConnection = 0;
+ } else {
+ d->existingFileToOpen = QString::null;
+ d->selectedExistingConnection
+ = d->openExistingConnWidget->selectedConnectionData();
+ }
+ d->result = OpenExistingResult;
+ }
+ else {
+ d->result = OpenRecentResult;
+ }
+ }
+
+ //save settings
+ KGlobal::config()->setGroup("Startup");
+ if (d->openExistingConnWidget)
+ KGlobal::config()->writeEntry("OpenExistingType",
+ (d->openExistingConnWidget->selectedConnectionType() == KexiConnSelectorWidget::FileBased)
+ ? "File" : "Server");
+ if (d->chkDoNotShow)
+ KGlobal::config()->writeEntry("ShowStartupDialog",!d->chkDoNotShow->isChecked());
+
+ KGlobal::config()->sync();
+
+ KDialogBase::done(r);
+}
+
+void KexiStartupDialog::reject()
+{
+// d->result = CancelResult;
+ KDialogBase::reject();
+}
+
+void KexiStartupDialog::setupPageTemplates()
+{
+ d->pageTemplates = addPage( i18n("&Create Project") );
+ QVBoxLayout *lyr = new QVBoxLayout( d->pageTemplates, 0, KDialogBase::spacingHint() );
+
+ d->templatesWidget = new KJanusWidget(
+ d->pageTemplates, "templatesWidget", KJanusWidget::IconList);
+ {//aaa! dirty hack
+ d->templatesWidget_IconListBox = d->templatesWidget->child(0,"KListBox");
+ if (d->templatesWidget_IconListBox)
+ d->templatesWidget_IconListBox->installEventFilter(this);
+ }
+ lyr->addWidget(d->templatesWidget);
+ connect(d->templatesWidget, SIGNAL(aboutToShowPage(QWidget*)), this, SLOT(slotPageShown(QWidget*)));
+
+ if (d->dialogOptions & CheckBoxDoNotShowAgain) {
+ d->chkDoNotShow = new QCheckBox(i18n("Don't show me this dialog again"), d->pageTemplates, "chkDoNotShow");
+ lyr->addWidget(d->chkDoNotShow);
+ }
+
+ //template groups:
+ QFrame *templPageFrame;
+ QVBoxLayout *tmplyr;
+ int itemID = 0; //used just to set up templatesSectionID_*
+
+ //- page "blank db"
+ d->templatesSectionID_blank = itemID++;
+ QString clickMsg( "\n\n" + i18n("Click \"OK\" button to proceed.") );
+ templPageFrame = d->templatesWidget->addPage(
+ i18n("Blank Database"), i18n("New Blank Database Project"), DesktopIcon("empty") );
+ tmplyr = new QVBoxLayout(templPageFrame, 0, KDialogBase::spacingHint());
+ QLabel *lbl_blank = new QLabel(
+ i18n("Kexi will create a new blank database project.")+clickMsg, templPageFrame );
+ lbl_blank->setAlignment(Qt::AlignAuto|Qt::AlignTop|Qt::WordBreak);
+ lbl_blank->setMargin(0);
+ tmplyr->addWidget( lbl_blank );
+ tmplyr->addStretch(1);
+
+#ifdef DB_TEMPLATES
+ //- page "templates"
+ d->templatesSectionID_templates = itemID++;
+ QString none;
+ QString kexi_sqlite_icon_name
+ = KMimeType::mimeType( KexiDB::Driver::defaultFileBasedDriverMimeType() )->icon(none,0);
+ templPageFrame = d->templatesWidget->addPage (
+ i18n("Keep this text narrow: split to multiple rows if needed", "Create From\nTemplate"),
+ i18n("New Database Project From Template"), DesktopIcon(kexi_sqlite_icon_name) );
+ tmplyr = new QVBoxLayout(templPageFrame, 0, KDialogBase::spacingHint());
+ QLabel *lbl_templ = new QLabel(
+ i18n("Kexi will create a new database project using selected template.\n"
+ "Select template and click \"OK\" button to proceed."), templPageFrame );
+ lbl_templ->setAlignment(Qt::AlignAuto|Qt::AlignTop|Qt::WordBreak);
+ lbl_templ->setMargin(0);
+ tmplyr->addWidget( lbl_templ );
+
+ d->viewTemplates = new KexiStartupDialogTemplatesPage( templPageFrame );
+ tmplyr->addWidget( d->viewTemplates );
+ connect(d->viewTemplates,SIGNAL(selected(const QString&)),
+ this,SLOT(templateSelected(const QString&)));
+/* connect(d->viewTemplates->templates,SIGNAL(returnPressed(QIconViewItem*)),
+ this,SLOT(templateItemExecuted(QIconViewItem*)));
+ connect(d->viewTemplates->templates,SIGNAL(currentChanged(QIconViewItem*)),
+ this,SLOT(templateItemSelected(QIconViewItem*)));*/
+/*later
+ templPageFrame = d->templatesWidget->addPage (
+ i18n("Personal Databases"), i18n("New Personal Database Project Templates"), DesktopIcon("folder_home") );
+ tmplyr = new QVBoxLayout(templPageFrame, 0, KDialogBase::spacingHint());
+ d->viewPersonalTempl = new TemplatesPage( Vertical, templPageFrame, "personal_page" );
+ tmplyr->addWidget( d->viewPersonalTempl );
+ connect(d->viewPersonalTempl->templates,SIGNAL(doubleClicked(QIconViewItem*)),this,SLOT(templateItemExecuted(QIconViewItem*)));
+ connect(d->viewPersonalTempl->templates,SIGNAL(returnPressed(QIconViewItem*)),this,SLOT(templateItemExecuted(QIconViewItem*)));
+ connect(d->viewPersonalTempl->templates,SIGNAL(currentChanged(QIconViewItem*)),this,SLOT(templateItemSelected(QIconViewItem*)));
+*/
+
+ //- page "business db"
+/*later
+ d->templatesSectionID_custom2 = itemID++;
+ templPageFrame = d->templatesWidget->addPage (
+ i18n("Business Databases"), i18n("New Business Database Project Templates"),
+ DesktopIcon( "business_user" ));
+ tmplyr = new QVBoxLayout(templPageFrame, 0, KDialogBase::spacingHint());
+ d->viewBusinessTempl = new TemplatesPage( Vertical, templPageFrame, "business_page" );
+ tmplyr->addWidget( d->viewBusinessTempl );
+ connect(d->viewBusinessTempl->templates,SIGNAL(doubleClicked(QIconViewItem*)),this,SLOT(templateItemExecuted(QIconViewItem*)));
+ connect(d->viewBusinessTempl->templates,SIGNAL(returnPressed(QIconViewItem*)),this,SLOT(templateItemExecuted(QIconViewItem*)));
+ connect(d->viewBusinessTempl->templates,SIGNAL(currentChanged(QIconViewItem*)),this,SLOT(templateItemSelected(QIconViewItem*)));
+*/
+#endif //DB_TEMPLATES
+
+ //- page "import db"
+ d->templatesSectionID_import = itemID++;
+ templPageFrame = d->templatesWidget->addPage(
+ i18n("Import Existing\nDatabase"), i18n("Import Existing Database as New Database Project"),
+ DesktopIcon("database_import") );
+ tmplyr = new QVBoxLayout(templPageFrame, 0, KDialogBase::spacingHint());
+ QLabel *lbl_import = new QLabel(
+ i18n("Kexi will import the structure and data of an existing database as a new database project.")
+ +clickMsg, templPageFrame );
+ lbl_import->setAlignment(Qt::AlignAuto|Qt::AlignTop|Qt::WordBreak);
+ lbl_import->setMargin(0);
+ tmplyr->addWidget( lbl_import );
+ tmplyr->addStretch(1);
+}
+
+void KexiStartupDialog::slotPageShown(QWidget *page)
+{
+ int idx = d->templatesWidget->pageIndex(page);
+// KIconView *templ = 0;
+ if (idx==d->templatesSectionID_blank) {//blank
+// kdDebug() << "blank" << endl;
+ }
+ else if (idx==d->templatesSectionID_import) {
+ }
+#ifdef DB_TEMPLATES
+ else if (idx==d->templatesSectionID_templates) {
+ d->viewTemplates->populate();
+ }
+/*later? KIconView *templ = d->viewTemplates->templates;
+ if (templ->count()==0) {
+ //add items (on demand):
+ d->viewTemplates->addItem("cd_catalog", i18n("CD Catalog"),
+ i18n("Easy-to-use database for storing information about your CD collection."),
+ DesktopIcon("cdrom_unmount"));
+ d->viewTemplates->addItem("expenses", i18n("Expenses"),
+ i18n("A database for managing your personal expenses."),
+ DesktopIcon("kcalc"));
+ d->viewTemplates->addItem("image_gallery", i18n("Image Gallery"),
+ i18n("A database for archiving your image collection in a form of gallery."),
+ DesktopIcon("icons"));
+ }
+ }
+ else if (idx==d->templatesSectionID_custom2) {//business
+ templ = d->viewBusinessTempl->templates;
+ if (templ->count()==0) {
+ //add items (on demand):
+ d->viewBusinessTempl->addItem("address_book", i18n("Address Book"),
+ i18n("A database that offers you a contact information"),
+ DesktopIcon("contents"));
+ }
+ }*/
+#endif
+ updateDialogOKButton(d->pageTemplates);
+}
+
+#if 0
+void KexiStartupDialog::templateItemSelected(QIconViewItem *)
+{
+ updateDialogOKButton(d->pageTemplates);
+}
+
+void KexiStartupDialog::templateItemExecuted(QIconViewItem *item)
+{
+ if (!item)
+ return;
+// updateSelectedTemplateKeyInfo();
+#ifdef DB_TEMPLATES
+ accept();
+#endif
+}
+
+void KexiStartupDialog::updateSelectedTemplateKeyInfo()
+{
+ if (activePageIndex()!=d->pageTemplatesID) {//not a 'new db' tab is selected
+ d->selectedTemplateKey=QString::null;
+ return;
+ }
+ QIconViewItem *item;
+ if (d->templatesWidget->activePageIndex()==d->templatesSectionID_blank) {
+ d->selectedTemplateKey = "blank";
+ }
+ else if (d->templatesWidget->activePageIndex()==d->templatesSectionID_import) {
+ d->selectedTemplateKey = "import";
+ }
+#ifdef DB_TEMPLATES
+ else if (d->templatesWidget->activePageIndex()==d->templatesSectionID_templates) {
+ item = d->viewTemplates->templates->currentItem();
+ if (!item) {
+ d->selectedTemplateKey=QString::null;
+ return;
+ }
+ d->selectedTemplateKey=QString("personal/")+static_cast<TemplateItem*>(item)->key;
+ }
+/*later?
+ else if (d->templatesWidget->activePageIndex()==d->templatesSectionID_custom2) {
+ item = d->viewBusinessTempl->templates->currentItem();
+ if (!item) {
+ d->selectedTemplateKey=QString::null;
+ return;
+ }
+ d->selectedTemplateKey=QString("business/")+static_cast<TemplateItem*>(item)->key;
+ }*/
+#endif
+}
+#endif // 0
+
+void KexiStartupDialog::tabShown(QWidget *w)
+{
+// kdDebug() << "KexiStartupDialog::tabShown " << (long)w << " "<< long(d->pageTemplates)<<endl;
+
+ updateDialogOKButton(w);
+
+ if (w==d->pageOpenExisting) {
+ d->openExistingConnWidget->setFocus();
+ }
+}
+
+void KexiStartupDialog::updateDialogOKButton(QWidget *w)
+{
+ if (!w) {
+ int idx = activePageIndex();
+ if (idx==d->pageTemplatesID)
+ w = d->pageTemplates;
+ else if (idx==d->pageOpenExistingID)
+ w = d->pageOpenExisting;
+ else if (idx==d->pageOpenRecentID)
+ w = d->pageOpenRecent;
+
+ if (!w)
+ return;
+ }
+ bool enable = true;
+ if (w==d->pageTemplates) {
+ int t_id = d->templatesWidget->activePageIndex();
+#ifdef DB_TEMPLATES
+ enable = (t_id==d->templatesSectionID_blank || d->templatesSectionID_import
+ || (t_id==d->templatesSectionID_templates && !d->viewTemplates->selectedFileName().isEmpty()));
+#else
+ enable = (t_id==d->templatesSectionID_blank || d->templatesSectionID_import);
+#endif
+ }
+ else if (w==d->pageOpenExisting) {
+// enable = !d->openExistingFileDlg->currentURL().path().isEmpty();
+ enable =
+ (d->openExistingConnWidget->selectedConnectionType()==KexiConnSelectorWidget::FileBased)
+ ? !d->openExistingFileDlg->currentFileName().isEmpty()
+ : (bool)d->openExistingConnWidget->selectedConnectionData();
+ }
+ else if (w==d->pageOpenRecent) {
+ enable = (d->prj_selector->selectedProjectData()!=0);
+ }
+ enableButton(Ok,enable);
+}
+
+/*QString KexiStartupDialog::selectedTemplateKey() const
+{
+ return d->selectedTemplateKey;
+}*/
+
+void KexiStartupDialog::setupPageOpenExisting()
+{
+ if (d->singlePage)
+ d->pageOpenExisting = plainPage();
+ else
+ d->pageOpenExisting = addPage( i18n("Open &Existing Project") );
+ QVBoxLayout *lyr = new QVBoxLayout( d->pageOpenExisting, 0, KDialogBase::spacingHint() );
+
+ d->openExistingConnWidget = new KexiConnSelectorWidget(*d->connSet,
+ ":OpenExistingOrCreateNewProject",
+ d->pageOpenExisting, "KexiConnSelectorWidget");
+ d->openExistingConnWidget->hideConnectonIcon();
+ lyr->addWidget( d->openExistingConnWidget );
+ if (KGlobal::config()->readEntry("OpenExistingType","File")=="File")
+ d->openExistingConnWidget->showSimpleConn();
+ else {
+ d->openExistingConnWidget->showSimpleConn();
+ d->openExistingConnWidget->showAdvancedConn();
+ }
+ d->openExistingFileDlg = d->openExistingConnWidget->m_fileDlg;
+ connect(d->openExistingFileDlg,SIGNAL(accepted()),this,SLOT(accept()));
+ connect(d->openExistingConnWidget,SIGNAL(connectionItemExecuted(ConnectionDataLVItem*)),
+ this,SLOT(connectionItemForOpenExistingExecuted(ConnectionDataLVItem*)));
+ connect(d->openExistingConnWidget,SIGNAL(connectionItemHighlighted(ConnectionDataLVItem*)),
+ this,SLOT(connectionItemForOpenExistingHighlighted(ConnectionDataLVItem*)));
+}
+
+void KexiStartupDialog::connectionItemForOpenExistingExecuted(ConnectionDataLVItem *item)
+{
+ if (!item)
+ return;
+ accept();
+}
+
+void KexiStartupDialog::connectionItemForOpenExistingHighlighted(ConnectionDataLVItem *item)
+{
+ actionButton(KDialogBase::Ok)->setEnabled(item);
+}
+
+void KexiStartupDialog::slotOk() {
+// kdDebug()<<"KexiStartupDialog::slotOk()"<<endl;
+ if (activePageIndex()==d->pageOpenExistingID) {
+ if (d->openExistingFileDlg) {
+ if (d->openExistingFileDlg->okButton())
+ d->openExistingFileDlg->okButton()->animateClick();
+// return;
+ }
+ }
+ KDialogBase::slotOk();
+}
+
+void KexiStartupDialog::showSimpleConnForOpenExisting()
+{
+// kdDebug() << "simple" << endl;
+ d->openExistingConnWidget->showSimpleConn();
+}
+
+void KexiStartupDialog::showAdvancedConnForOpenExisting()
+{
+// kdDebug() << "adv" << endl;
+ d->openExistingConnWidget->showAdvancedConn();
+}
+
+QString KexiStartupDialog::selectedFileName() const
+{
+ if (d->result == OpenExistingResult)
+ return d->existingFileToOpen;
+ else if (d->result == CreateFromTemplateResult && d->viewTemplates)
+ return d->viewTemplates->selectedFileName();
+ else
+ return QString::null;
+}
+
+KexiDB::ConnectionData* KexiStartupDialog::selectedExistingConnection() const
+{
+ return d->selectedExistingConnection;
+}
+
+void KexiStartupDialog::existingFileSelected(const QString &f)
+{
+ if (f.isEmpty())
+ return;
+ d->existingFileToOpen=f;
+ updateDialogOKButton(d->openExistingFileDlg);
+}
+
+void KexiStartupDialog::setupPageOpenRecent()
+{
+#ifdef KEXI_STARTUP_SHOW_RECENT
+ d->pageOpenRecent = addPage( i18n("Open &Recent Project") );
+ QVBoxLayout *lyr = new QVBoxLayout( d->pageOpenRecent, 0, KDialogBase::spacingHint() );
+ lyr->addWidget( d->prj_selector = new KexiProjectSelectorWidget(
+ d->pageOpenRecent, "prj_selector", d->recentProjects ) );
+ connect(d->prj_selector,SIGNAL(projectExecuted(KexiProjectData*)),
+ this,SLOT(recentProjectItemExecuted(KexiProjectData*)));
+#endif
+}
+
+KexiProjectData* KexiStartupDialog::selectedProjectData() const
+{
+ if (activePageIndex()==d->pageOpenRecentID) {
+ return d->prj_selector->selectedProjectData();
+ }
+ return 0;
+}
+
+void KexiStartupDialog::recentProjectItemExecuted(KexiProjectData *data)
+{
+ updateDialogOKButton(d->pageOpenRecent);
+ if (!data)
+ return;
+ accept();
+}
+
+//! used for accepting templates dialog with just return key press
+bool KexiStartupDialog::eventFilter( QObject *o, QEvent *e )
+{
+ if (o==d->templatesWidget_IconListBox && d->templatesWidget_IconListBox) {
+ if (e->type()==QEvent::KeyPress
+ && (static_cast<QKeyEvent*>(e)->key()==Key_Enter || static_cast<QKeyEvent*>(e)->key()==Key_Return)
+ || e->type()==QEvent::MouseButtonDblClick)
+ {
+ const int t_id = d->templatesWidget->activePageIndex();
+ if (t_id==d->templatesSectionID_blank || t_id==d->templatesSectionID_import) {
+
+ accept();
+ }
+ }
+ }
+ return KDialogBase::eventFilter(o,e);
+}
+
+// internal reimplementation
+int KexiStartupDialog::activePageIndex() const
+{
+ if (!d->singlePage) {
+// kdDebug() << "int KexiStartupDialog::activePageIndex()" << KDialogBase::activePageIndex() << endl;
+ return KDialogBase::activePageIndex();
+ }
+ kdDebug() << "int KexiStartupDialog::activePageIndex() == " << 0 << endl;
+ return 0; //there is always "plain page" #0 selected
+}
+
+void KexiStartupDialog::templateSelected(const QString& fileName)
+{
+ if (!fileName.isEmpty())
+ accept();
+}
+
+QValueList<KexiProjectData::ObjectInfo> KexiStartupDialog::autoopenObjects() const
+{
+ if (d->result != CreateFromTemplateResult || !d->viewTemplates)
+ QValueList<KexiProjectData::ObjectInfo>();
+
+ return d->viewTemplates->autoopenObjectsForSelectedTemplate();
+}
+
+#include "KexiStartupDialog.moc"
diff --git a/kexi/main/startup/KexiStartupDialog.h b/kexi/main/startup/KexiStartupDialog.h
new file mode 100644
index 00000000..41f6064b
--- /dev/null
+++ b/kexi/main/startup/KexiStartupDialog.h
@@ -0,0 +1,185 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KexiStartupDialog_h
+#define KexiStartupDialog_h
+
+#include <kdialogbase.h>
+#include <kicondialog.h>
+#include <kiconview.h>
+#include <kfileiconview.h>
+#include <kfiledialog.h>
+
+#include <qlabel.h>
+#include <qsplitter.h>
+
+#include <kexidb/connectiondata.h>
+#include <core/kexiprojectdata.h>
+
+class KexiStartupDialogPrivate;
+class KexiProjectData;
+class KexiProjectSet;
+class KexiDBConnectionSet;
+class ConnectionDataLVItem;
+
+/*!
+ This class is used to show the template/open-existing/open-recent tabbed dialog
+ on Kexi startup. If only one page is shown, tab is no displayed, so dialog
+ becomes a normal "plain" type dialog.
+ */
+class KEXIMAIN_EXPORT KexiStartupDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ /*! The Dialog returns one of these values depending
+ on the input of the user.
+ CancelResult The user pressed 'Cancel'
+ CreateBlankResult The user selected a template
+ CreateFromTemplateResult The user selected a template
+ ImportResult The user selected a template
+ OpenExistingResult The user has chosen an existing connection or db file
+ OpenRecentResult The user selected one of recently used databases
+ */
+ enum Result {
+ CancelResult, //!< The user has pressed 'Cancel'
+ CreateBlankResult, //!< The user has selected a template
+ CreateFromTemplateResult, //!< The user has selected a template to be used for creating a new db
+ ImportResult, //!< The user has chosen to import db
+ OpenExistingResult, //!< The user has chosen an existing connection or db file
+ OpenRecentResult //!< The user has selected one of recently used databases
+ };
+
+ /*!
+ To configure the dialog you have to use this enum
+ (any !=0 or'ed value is ok)
+ - Templates Show "Templates" tab
+ - OpenExisting Show "Open existing" tab
+ - OpenRecent Show "Recent" tab
+ - Everything Show everything above
+ */
+ enum DialogType { Templates = 1, OpenExisting = 2, OpenRecent = 4, Everything = (1+2+4) };
+
+ /*! Options for a dialog
+ (any or'ed value or 0 is ok)
+ - CheckBoxDoNotShowAgain Adds "do not show this window" checkbox at the bottom
+ */
+ enum DialogOptions { CheckBoxDoNotShowAgain = 1 };
+
+ /*! Creates a dialog.
+ @param dialogType see DialogType description
+ @param dialogOptions see dialogOptions description
+ @param recentProjects a set of recent projects' info, used for "Open recent" tab
+ @param connSet conenction set used to present available conenctions
+ in "Open Existing" tab. Pass an empty object is this tab is not used.
+ @param parent parent widget, if any.
+ @param name name of this object.
+ */
+ KexiStartupDialog(
+ int dialogType,
+ int dialogOptions,
+ KexiDBConnectionSet& connSet,
+ KexiProjectSet& recentProjects,
+ QWidget *parent = 0, const char *name = 0 );
+ ~KexiStartupDialog();
+
+ /*! \return true if startup dialog should be shown (info is taken from kexi config)
+ */
+ static bool shouldBeShown();
+
+ /*! Executes dialog.
+ \return one of Result values. Use this after dialog is closed. */
+ int result() const;
+
+ /*! \return data of selected Kexi project (if "Open Recent" tab was selected).
+ Returns NULL if no selection has been made or other tab was selected.
+ */
+ KexiProjectData* selectedProjectData() const;
+
+ /*! \return name of selected Kexi project file
+ (if result() == OpenExistingResult)
+ or name of template file to be used for creating a new database.
+ (if result() == CreateFromTemplateResult).
+ Returns empty string if no such selection has been made or other tab was selected.
+ */
+ QString selectedFileName() const;
+
+ /*! \return "autoopen" objects defined for selected template.
+ Only makes sense if template was used. */
+ QValueList<KexiProjectData::ObjectInfo> autoopenObjects() const;
+
+ /*! \return a pointer to selected Kexi connection data.
+ (if "Open Existing" tab was selected and this connection data was clicked).
+ Returns NULL if no such selection has been made or other tab was selected.
+ */
+ KexiDB::ConnectionData* selectedExistingConnection() const;
+
+ /*! Reimplemented for internal reasons */
+ virtual void show();
+
+public slots:
+
+protected slots:
+ virtual void done(int r);
+ virtual void reject();
+ virtual void slotOk();
+
+ //! slot activated when one of page in templates window is shown
+ void slotPageShown(QWidget *page);
+/*
+ //! Any icon view item has been executed (dblclicked)
+ void templateItemExecuted(QIconViewItem *item);
+
+ //! Any icon view item has been selected
+ void templateItemSelected(QIconViewItem *item);*/
+
+ //! Any tab has been selected
+ void tabShown(QWidget *w);
+
+ void templateSelected(const QString& fileName);
+
+ //! helper
+ void recentProjectItemExecuted(KexiProjectData *data);
+ void existingFileSelected(const QString &f);
+ void showSimpleConnForOpenExisting();
+ void showAdvancedConnForOpenExisting();
+ void connectionItemForOpenExistingExecuted(ConnectionDataLVItem *item);
+ void connectionItemForOpenExistingHighlighted(ConnectionDataLVItem *item);
+
+protected:
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ //! helper: updates a state of dialog's OK button
+ void updateDialogOKButton(QWidget *w);
+
+ //! internal reimplementation
+ int activePageIndex() const;
+private:
+ void setupPageTemplates();
+ void setupPageOpenExisting();
+ void setupPageOpenRecent();
+
+ //! used internally on accepting templates selection
+// void updateSelectedTemplateKeyInfo();
+
+ KexiStartupDialogPrivate *d;
+};
+
+#endif
+
diff --git a/kexi/main/startup/KexiStartupDialogTemplatesPage.cpp b/kexi/main/startup/KexiStartupDialogTemplatesPage.cpp
new file mode 100644
index 00000000..3a64fbac
--- /dev/null
+++ b/kexi/main/startup/KexiStartupDialogTemplatesPage.cpp
@@ -0,0 +1,157 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KexiStartupDialogTemplatesPage.h"
+
+#include <core/kexi.h>
+#include <core/kexitemplateloader.h>
+#include "KexiProjectSelector.h"
+#include "KexiOpenExistingFile.h"
+#include "KexiConnSelector.h"
+#include "KexiConnSelectorBase.h"
+
+#include <qheader.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+
+#ifdef KEXI_SHOW_UNIMPLEMENTED
+#define KEXI_STARTUP_SHOW_TEMPLATES
+#define KEXI_STARTUP_SHOW_RECENT
+#endif
+
+/*QPixmap createIcon()
+{
+
+}*/
+
+/*QString createText(const QString& name, const QString& description)
+{
+ QString txt = "<H2>" + name + "</H2>";
+ if (description.isEmpty())
+ return name + description
+}*/
+
+//! @internal
+class TemplateItem : public KListViewItem
+{
+ public:
+ TemplateItem(QListView* parent, const QString& aFilename,
+ const QString& name, const QString& description, const QPixmap& icon,
+ const QValueList<KexiProjectData::ObjectInfo>& aAutoopenObjects)
+ : KListViewItem(parent, name + "\n" + description)
+ , autoopenObjects(aAutoopenObjects)
+ , filename(aFilename)
+ {
+ setPixmap(0, icon);
+ }
+ ~TemplateItem() {}
+
+ QValueList<KexiProjectData::ObjectInfo> autoopenObjects;
+ QString filename;
+};
+
+//-----------------------
+
+KexiStartupDialogTemplatesPage::KexiStartupDialogTemplatesPage( QWidget * parent )
+ : KListView(parent, "KexiStartupDialogTemplatesPage")
+ , m_popuplated(false)
+{
+ addColumn(QString::null);
+ header()->hide();
+ setColumnWidthMode(0, Maximum);
+ setResizeMode(LastColumn);
+ setItemMargin(6);
+ connect(this,SIGNAL(executed(QListViewItem*)), this, SLOT(slotExecuted(QListViewItem*)));
+}
+
+KexiStartupDialogTemplatesPage::~KexiStartupDialogTemplatesPage()
+{
+}
+
+void KexiStartupDialogTemplatesPage::populate()
+{
+ if (m_popuplated)
+ return;
+ m_popuplated = true;
+ KexiTemplateInfo::List list = KexiTemplateLoader::loadListInfo();
+ foreach( QValueList<KexiTemplateInfo>::ConstIterator, it, list ) {
+ new TemplateItem(this, (*it).filename, (*it).name,
+ (*it).description, (*it).icon, (*it).autoopenObjects);
+ }
+ if (firstChild())
+ setSelected(firstChild(), true);
+
+// templates = new KIconView(this, "templates");
+// templates->setItemsMovable(false);
+// templates->setShowToolTips(false);
+// info = new KTextBrowser(this,"info");
+// setResizeMode(templates,KeepSize);
+// setResizeMode(info,KeepSize);
+// connect(templates,SIGNAL(selectionChanged(QIconViewItem*)),this,SLOT(itemClicked(QIconViewItem*)));
+}
+
+/*
+void TemplatesPage::addItem(const QString& key, const QString& name,
+ const QString& description, const QPixmap& icon)
+{
+ TemplateItem *item = new TemplateItem(templates, name, icon);
+ item->key=key;
+ item->name=name;
+ item->description=description;
+}
+
+void TemplatesPage::itemClicked(QIconViewItem *item) {
+ if (!item) {
+ info->setText("");
+ return;
+ }
+ QString t = QString("<h2>%1</h2><p>%2</p>")
+ .arg(static_cast<TemplateItem*>(item)->name)
+ .arg(static_cast<TemplateItem*>(item)->description);
+#ifndef DB_TEMPLATES
+ t += QString("<p>") + i18n("We are sorry, templates are not yet available.") +"</p>";
+#endif
+
+ info->setText( t );
+}*/
+
+QString KexiStartupDialogTemplatesPage::selectedFileName() const
+{
+ TemplateItem* templateItem = static_cast<TemplateItem*>(selectedItem());
+ return templateItem ? templateItem->filename : QString::null;
+}
+
+QValueList<KexiProjectData::ObjectInfo>
+KexiStartupDialogTemplatesPage::autoopenObjectsForSelectedTemplate() const
+{
+ TemplateItem* templateItem = static_cast<TemplateItem*>(selectedItem());
+ return templateItem ? templateItem->autoopenObjects : QValueList<KexiProjectData::ObjectInfo>();
+}
+
+void KexiStartupDialogTemplatesPage::slotExecuted(QListViewItem* item)
+{
+ TemplateItem* templateItem = static_cast<TemplateItem*>(item);
+ if (!templateItem)
+ return;
+
+ emit selected(templateItem->filename);
+}
+
+#include "KexiStartupDialogTemplatesPage.moc"
diff --git a/kexi/main/startup/KexiStartupDialogTemplatesPage.h b/kexi/main/startup/KexiStartupDialogTemplatesPage.h
new file mode 100644
index 00000000..8613065f
--- /dev/null
+++ b/kexi/main/startup/KexiStartupDialogTemplatesPage.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright (C) 2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KexiStartupDialogTemplatesPage_h
+#define KexiStartupDialogTemplatesPage_h
+
+#include <klistview.h>
+#include <core/kexiprojectdata.h>
+
+/*! Helper class for displaying templates set with description. */
+class KEXIMAIN_EXPORT KexiStartupDialogTemplatesPage : public KListView
+{
+ Q_OBJECT
+
+ public:
+ KexiStartupDialogTemplatesPage( QWidget * parent = 0 );
+ ~KexiStartupDialogTemplatesPage();
+// void addItem(const QString& key, const QString& name,
+// const QString& description, const QPixmap& icon);
+
+ QString selectedFileName() const;
+
+ QValueList<KexiProjectData::ObjectInfo> autoopenObjectsForSelectedTemplate() const;
+
+ void populate();
+
+ signals:
+ void selected(const QString& filename);
+
+ protected slots:
+ void slotExecuted(QListViewItem* item);
+
+// void itemClicked(QIconViewItem *item);
+
+ private:
+ bool m_popuplated : 1;
+// KIconView *templates;
+// KTextBrowser *info;
+};
+
+#endif
diff --git a/kexi/main/startup/KexiStartupFileDialog.cpp b/kexi/main/startup/KexiStartupFileDialog.cpp
new file mode 100644
index 00000000..d2869925
--- /dev/null
+++ b/kexi/main/startup/KexiStartupFileDialog.cpp
@@ -0,0 +1,422 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KexiStartupFileDialog.h"
+
+#include <kexidb/driver.h>
+#include <core/kexi.h>
+#include <kexiutils/utils.h>
+
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qpushbutton.h>
+#include <qapplication.h>
+
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmimetype.h>
+#include <kfile.h>
+#include <kurlcombobox.h>
+
+KexiStartupFileDialog::KexiStartupFileDialog(
+ const QString& startDirOrVariable, int mode,
+ QWidget *parent, const char *name)
+ : KexiStartupFileDialogBase(startDirOrVariable, "", parent, name, 0)
+ , m_confirmOverwrites(true)
+ , m_filtersUpdated(false)
+{
+ setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
+ setMode( mode );
+
+ QPoint point( 0, 0 );
+ reparent( parentWidget(), point );
+
+ if (layout())
+ layout()->setMargin(0);
+ setMinimumHeight(100);
+ setSizeGripEnabled ( false );
+
+ //dirty hack to customize filedialog view:
+ {
+ QObjectList *l = queryList( "QPushButton" );
+ QObjectListIt it( *l );
+ QObject *obj;
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ static_cast<QPushButton*>(obj)->hide();
+ }
+ delete l;
+ }
+ {
+ QObjectList *l = queryList("QWidget");
+ QObjectListIt it( *l );
+ QObject *obj;
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ static_cast<QWidget*>(obj)->installEventFilter(this);
+ }
+ delete l;
+ }
+
+#ifdef Q_WS_WIN
+ if (startDirOrVariable.startsWith(":"))
+ m_lastVisitedPathsVariable = startDirOrVariable; //store for later use
+#else
+ toggleSpeedbar(false);
+ setFocusProxy( locationEdit );//locationWidget() );
+#endif
+}
+
+KexiStartupFileDialog::~KexiStartupFileDialog()
+{
+#ifdef Q_WS_WIN
+ saveLastVisitedPath(currentFileName());
+#endif
+}
+
+void KexiStartupFileDialog::setMode(int mode)
+{
+ //delayed
+ m_mode = mode;
+ m_filtersUpdated = false;
+}
+
+QStringList KexiStartupFileDialog::additionalFilters() const
+{
+ return m_additionalMimeTypes;
+}
+
+void KexiStartupFileDialog::setAdditionalFilters(const QStringList &mimeTypes)
+{
+ //delayed
+ m_additionalMimeTypes = mimeTypes;
+ m_filtersUpdated = false;
+}
+
+QStringList KexiStartupFileDialog::excludedFilters() const
+{
+ return m_excludedMimeTypes;
+}
+
+void KexiStartupFileDialog::setExcludedFilters(const QStringList &mimeTypes)
+{
+ //delayed
+ m_excludedMimeTypes = mimeTypes;
+ m_filtersUpdated = false;
+}
+
+void KexiStartupFileDialog::updateFilters()
+{
+ if (m_filtersUpdated)
+ return;
+ m_filtersUpdated = true;
+
+ m_lastFileName = QString::null;
+// m_lastUrl = KURL();
+
+ clearFilter();
+
+ QString filter;
+ KMimeType::Ptr mime;
+ QStringList allfilters;
+
+ const bool normalOpeningMode = m_mode & Opening && !(m_mode & Custom);
+ const bool normalSavingMode = m_mode & SavingFileBasedDB && !(m_mode & Custom);
+
+ if (normalOpeningMode || normalSavingMode) {
+ mime = KMimeType::mimeType( KexiDB::Driver::defaultFileBasedDriverMimeType() );
+ if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
+ filter += KexiUtils::fileDialogFilterString(mime);
+ allfilters += mime->patterns();
+ }
+ }
+ if (normalOpeningMode || m_mode & SavingServerBasedDB) {
+ mime = KMimeType::mimeType("application/x-kexiproject-shortcut");
+ if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
+ filter += KexiUtils::fileDialogFilterString(mime);
+ allfilters += mime->patterns();
+ }
+ }
+ if (normalOpeningMode || m_mode & SavingServerBasedDB) {
+ mime = KMimeType::mimeType("application/x-kexi-connectiondata");
+ if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
+ filter += KexiUtils::fileDialogFilterString(mime);
+ allfilters += mime->patterns();
+ }
+ }
+
+//! @todo hardcoded for MSA:
+ if (normalOpeningMode) {
+ mime = KMimeType::mimeType("application/x-msaccess");
+ if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
+ filter += KexiUtils::fileDialogFilterString(mime);
+ allfilters += mime->patterns();
+ }
+ }
+
+ foreach (QStringList::ConstIterator, it, m_additionalMimeTypes) {
+ if (*it == "all/allfiles")
+ continue;
+ if (m_excludedMimeTypes.find(*it)!=m_excludedMimeTypes.end())
+ continue;
+ filter += KexiUtils::fileDialogFilterString(*it);
+ mime = KMimeType::mimeType(*it);
+ allfilters += mime->patterns();
+ }
+
+ if (m_excludedMimeTypes.find("all/allfiles")==m_excludedMimeTypes.end())
+ filter += KexiUtils::fileDialogFilterString("all/allfiles");
+// mime = KMimeType::mimeType("all/allfiles");
+// if (mime) {
+// filter += QString(mime->patterns().isEmpty() ? "*" : mime->patterns().join(" "))
+// + "|" + mime->comment()+ " (*)\n";
+// }
+ //remove duplicates made because upper- and lower-case extenstions are used:
+ QStringList allfiltersUnique;
+ QDict<char> uniqueDict(499, false);
+ foreach (QStringList::ConstIterator, it, allfilters) {
+// kdDebug() << *it << endl;
+ uniqueDict.insert(*it, (char*)1);
+ }
+ foreach_dict (QDictIterator<char>, it, uniqueDict) {
+ allfiltersUnique += it.currentKey();
+ }
+ allfiltersUnique.sort();
+
+ if (allfiltersUnique.count()>1) {//prepend "all supoported files" entry
+ filter.prepend(allfilters.join(" ")+"|" + i18n("All Supported Files")
+ +" ("+allfiltersUnique.join(" ")+")\n");
+ }
+
+ if (filter.right(1)=="\n")
+ filter.truncate(filter.length()-1);
+ setFilter(filter);
+
+ if (m_mode & Opening) {
+ KexiStartupFileDialogBase::setMode( KFile::ExistingOnly | KFile::LocalOnly | KFile::File );
+ setOperationMode( KFileDialog::Opening );
+ } else {
+ KexiStartupFileDialogBase::setMode( KFile::LocalOnly | KFile::File );
+ setOperationMode( KFileDialog::Saving );
+ }
+}
+
+void KexiStartupFileDialog::show()
+{
+ m_filtersUpdated = false;
+ updateFilters();
+ KexiStartupFileDialogBase::show();
+}
+
+//KURL KexiStartupFileDialog::currentURL()
+QString KexiStartupFileDialog::currentFileName()
+{
+ setResult( QDialog::Accepted ); // selectedURL tests for it
+
+#ifdef Q_WS_WIN
+// QString path = selectedFile();
+ //js @todo
+// kdDebug() << "selectedFile() == " << path << " '" << url().fileName() << "' " << m_lineEdit->text() << endl;
+ QString path = dir()->absPath();
+ if (!path.endsWith("/") && !path.endsWith("\\"))
+ path.append("/");
+ path += m_lineEdit->text();
+// QString path = QFileInfo(selectedFile()).dirPath(true) + "/" + m_lineEdit->text();
+#else
+// QString path = locationEdit->currentText().stripWhiteSpace(); //url.path().stripWhiteSpace(); that does not work, if the full path is not in the location edit !!!!!
+ QString path=KexiStartupFileDialogBase::selectedURL().path();
+ kdDebug() << "prev selectedURL() == " << path <<endl;
+ kdDebug() << "locationEdit == " << locationEdit->currentText().stripWhiteSpace() <<endl;
+ //make sure user-entered path is acceped:
+ setSelection( locationEdit->currentText().stripWhiteSpace() );
+
+ path=KexiStartupFileDialogBase::selectedURL().path();
+ kdDebug() << "selectedURL() == " << path <<endl;
+
+#endif
+
+ if (!currentFilter().isEmpty()) {
+ if (m_mode & SavingFileBasedDB) {
+ QStringList filters = QStringList::split(" ", currentFilter()); //.first().stripWhiteSpace();
+ kdDebug()<< " filter == " << filters << endl;
+ QString ext = QFileInfo(path).extension(false);
+ bool hasExtension = false;
+ for (QStringList::ConstIterator filterIt = filters.constBegin();
+ filterIt != filters.constEnd() && !hasExtension; ++filterIt)
+ {
+ QString f( (*filterIt).stripWhiteSpace() );
+ hasExtension = !f.mid(2).isEmpty() && ext==f.mid(2);
+ }
+ if (!hasExtension) {
+ //no extension: add one
+ QString defaultExtension( m_defaultExtension );
+ if (defaultExtension.isEmpty())
+ defaultExtension = filters.first().stripWhiteSpace().mid(2); //first one
+ path+=(QString(".")+defaultExtension);
+ kdDebug() << "KexiStartupFileDialog::checkURL(): append extension, " << path << endl;
+ setSelection( path );
+ }
+ }
+ }
+ kdDebug() << "KexiStartupFileDialog::currentFileName() == " << path <<endl;
+ return path;
+// return KFileDialog::selectedURL();
+}
+
+//bool KexiStartupFileDialog::checkURL()
+bool KexiStartupFileDialog::checkFileName()
+{
+// KURL url = currentURL();
+// QString path = url.path().stripWhiteSpace();
+ QString path = currentFileName().stripWhiteSpace();
+
+// if (url.fileName().stripWhiteSpace().isEmpty()) {
+ if (path.isEmpty()) {
+ KMessageBox::error( this, i18n( "Enter a filename." ));
+ return false;
+ }
+
+ kdDebug() << "KexiStartupFileDialog::checkURL() path: " << path << endl;
+// kdDebug() << "KexiStartupFileDialog::checkURL() fname: " << url.fileName() << endl;
+//todo if ( url.isLocalFile() ) {
+ QFileInfo fi(path);
+ if (mode() & KFile::ExistingOnly) {
+ if ( !fi.exists() ) {
+ KMessageBox::error( this, "<qt>"+i18n( "The file \"%1\" does not exist." )
+ .arg( QDir::convertSeparators(path) ) );
+ return false;
+ }
+ else if (mode() & KFile::File) {
+ if (!fi.isFile()) {
+ KMessageBox::error( this, "<qt>"+i18n( "Enter a filename." ) );
+ return false;
+ }
+ else if (!fi.isReadable()) {
+ KMessageBox::error( this, "<qt>"+i18n( "The file \"%1\" is not readable." )
+ .arg( QDir::convertSeparators(path) ) );
+ return false;
+ }
+ }
+ }
+ else if (m_confirmOverwrites && !askForOverwriting( path, this )) {
+ return false;
+ }
+// }
+ return true;
+}
+
+//static
+bool KexiStartupFileDialog::askForOverwriting(const QString& filePath, QWidget *parent)
+{
+ QFileInfo fi(filePath);
+ if (!fi.exists())
+ return true;
+ const int res = KMessageBox::warningYesNo( parent, i18n( "The file \"%1\" already exists.\n"
+ "Do you want to overwrite it?").arg( QDir::convertSeparators(filePath) ), QString::null,
+ i18n("Overwrite"), KStdGuiItem::no() );
+ if (res == KMessageBox::Yes)
+ return true;
+ return false;
+}
+
+void KexiStartupFileDialog::accept()
+{
+// locationEdit->setFocus();
+// QKeyEvent ev(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
+// QApplication::sendEvent(locationEdit, &ev);
+// QApplication::postEvent(locationEdit, &ev);
+
+// kdDebug() << "KexiStartupFileDialog::accept() m_lastUrl == " << m_lastUrl.path() << endl;
+// if (m_lastUrl.path()==currentURL().path()) {//(js) to prevent more multiple kjob signals (I do not know why this is)
+ if (m_lastFileName==currentFileName()) {//(js) to prevent more multiple kjob signals (I do not know why this is)
+// m_lastUrl=KURL();
+ m_lastFileName=QString::null;
+ kdDebug() << "m_lastFileName==currentFileName()" << endl;
+#ifdef Q_WS_WIN
+ return;
+#endif
+ }
+// kdDebug() << "KexiStartupFileDialog::accept(): url = " << currentURL().path() << " " << endl;
+ kdDebug() << "KexiStartupFileDialog::accept(): path = " << currentFileName() << endl;
+// if ( checkURL() ) {
+ if ( checkFileName() ) {
+ emit accepted();
+ }
+// else {
+// m_lastUrl = KURL();
+// }
+// m_lastUrl = currentURL();
+ m_lastFileName = currentFileName();
+
+#ifdef Q_WS_WIN
+ saveLastVisitedPath(m_lastFileName);
+#endif
+}
+
+void KexiStartupFileDialog::reject()
+{
+ kdDebug() << "KexiStartupFileDialog: reject!" << endl;
+ emit rejected();
+}
+
+/*#ifndef Q_WS_WIN
+KURLComboBox *KexiStartupFileDialog::locationWidget() const
+{
+ return locationEdit;
+}
+#endif
+*/
+
+void KexiStartupFileDialog::setLocationText(const QString& fn)
+{
+#ifdef Q_WS_WIN
+ //js @todo
+ setSelection(fn);
+#else
+ setSelection(fn);
+// locationEdit->setCurrentText(fn);
+// locationEdit->lineEdit()->setEdited( true );
+// setSelection(fn);
+#endif
+}
+
+void KexiStartupFileDialog::setFocus()
+{
+#ifdef Q_WS_WIN
+ m_lineEdit->setFocus();
+#else
+ locationEdit->setFocus();
+#endif
+}
+
+bool KexiStartupFileDialog::eventFilter ( QObject * watched, QEvent * e )
+{
+ //filter-out ESC key
+ if (e->type()==QEvent::KeyPress && static_cast<QKeyEvent*>(e)->key()==Qt::Key_Escape
+ && static_cast<QKeyEvent*>(e)->state()==Qt::NoButton) {
+ static_cast<QKeyEvent*>(e)->accept();
+ emit rejected();
+ return true;
+ }
+ return KexiStartupFileDialogBase::eventFilter(watched,e);
+}
+
+#include "KexiStartupFileDialog.moc"
+
diff --git a/kexi/main/startup/KexiStartupFileDialog.h b/kexi/main/startup/KexiStartupFileDialog.h
new file mode 100644
index 00000000..87ebf7f4
--- /dev/null
+++ b/kexi/main/startup/KexiStartupFileDialog.h
@@ -0,0 +1,132 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KexiStartupFileDialog_h_
+#define _KexiStartupFileDialog_h_
+
+#include <kfiledialog.h>
+
+#ifdef Q_WS_WIN
+# include "KexiStartupFileDialogBase_win.h"
+#else
+ typedef KFileDialog KexiStartupFileDialogBase;
+#endif
+
+
+//! @short Widget for opening/saving files supported by Kexi
+class KEXIMAIN_EXPORT KexiStartupFileDialog : public KexiStartupFileDialogBase
+{
+ Q_OBJECT
+
+public:
+ /*! Dialog mode:
+ - Opening opens existing database (or shortcut)
+ - SavingFileBasedDB saves file-based database file
+ - SavingServerBasedDB saves server-based (shortcut) file
+ - CustomOpening can be used for opening other files, like CSV
+ */
+ typedef enum Mode {
+ Opening = 1,
+ SavingFileBasedDB = 2,
+ SavingServerBasedDB = 4,
+ Custom = 256
+ };
+
+ KexiStartupFileDialog(
+ const QString& startDirOrVariable, int mode, QWidget *parent=0, const char *name=0);
+
+ virtual ~KexiStartupFileDialog();
+
+ /*! Helper. Displays "The file %1 already exists. Do you want to overwrite it?" yes/no message box.
+ \a parent is used as a parent of the KMessageBox.
+ \return true if \a filePath file does not exists or user has agreed on overwriting,
+ false in user do not want to overwrite. */
+ static bool askForOverwriting(const QString& filePath, QWidget *parent = 0);
+
+ void setMode(int mode);
+
+ QStringList additionalFilters() const;
+
+ //! Sets additional filters list, e.g. "text/x-csv"
+ void setAdditionalFilters(const QStringList &mimeTypes);
+
+ QStringList excludedFilters() const;
+
+ //! Excludes filters list
+ void setExcludedFilters(const QStringList &mimeTypes);
+
+// KURL currentURL();
+ QString currentFileName();
+
+//#ifndef Q_WS_WIN
+// KURLComboBox *locationWidget() const;
+//#endif
+ //! just sets locationWidget()->setCurrentText(fn)
+ //! (and something similar on win32)
+ void setLocationText(const QString& fn);
+
+ //! Sets default extension which will be added after accepting
+ //! if user didn't provided one. This method is usable when there is
+ //! more than one filter so there is no rule what extension should be selected
+ //! (by default first one is selected).
+ void setDefaultExtension(const QString& ext) { m_defaultExtension = ext; }
+
+ /*! \return true if the current URL meets requies constraints
+ (i.e. exists or doesn't exist);
+ shows appropriate message box if needed. */
+ bool checkFileName();
+// bool checkURL();
+
+ /*! If true, user will be asked to accept overwriting existing file.
+ This is true by default. */
+ void setConfirmOverwrites(bool set) { m_confirmOverwrites = set; }
+
+ virtual bool eventFilter ( QObject * watched, QEvent * e );
+
+public slots:
+ virtual void show();
+
+ virtual void setFocus();
+
+ // Typing a file that doesn't exist closes the file dialog, we have to
+ // handle this case better here.
+ virtual void accept();
+
+signals:
+ //entered file name is accepted
+ void accepted();
+ void rejected();
+
+protected slots:
+ virtual void reject();
+
+private:
+ void updateFilters();
+
+// KURL m_lastUrl;
+ QString m_lastFileName;
+ int m_mode;
+ QStringList m_additionalMimeTypes, m_excludedMimeTypes;
+ QString m_defaultExtension;
+ bool m_confirmOverwrites : 1;
+ bool m_filtersUpdated : 1;
+};
+
+#endif
+
diff --git a/kexi/main/startup/KexiStartupFileDialogBase_win.h b/kexi/main/startup/KexiStartupFileDialogBase_win.h
new file mode 100644
index 00000000..7d7f56e0
--- /dev/null
+++ b/kexi/main/startup/KexiStartupFileDialogBase_win.h
@@ -0,0 +1,67 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KexiStartupFileDialogBase_win_h_
+#define _KexiStartupFileDialogBase_win_h_
+
+#include <qfiledialog.h>
+#include <qpushbutton.h>
+
+class KexiStartupFileDialogBasePrivate;
+
+/*! Wrapper for win32-like file dialog. QFileDialog is used for this.
+ Temporary moved from QKW KFileDialog implementation.
+ TODO: move to KDElibs/win32 KFileDialog wrapper
+*/
+class KexiStartupFileDialogBase : public QFileDialog
+{
+public:
+ KexiStartupFileDialogBase(const QString & dirName, const QString & filter = QString::null,
+ QWidget * parent = 0, const char * name = 0, bool modal = false );
+ ~KexiStartupFileDialogBase();
+
+ QPushButton * okButton() const { return m_okBtn; }
+
+ void clearFilter();
+ void setFilter(const QString& filter);
+ void setOperationMode( KFileDialog::OperationMode mode );
+ void setMode( KFile::Mode m );
+ void setMode( unsigned int m );
+ QString currentFilter() const;
+ void setMimeFilter( const QStringList& mimeTypes, const QString& defaultType = QString::null );
+
+ KFile::Mode mode() const;
+
+protected:
+ void init(const QString& startDir, const QString& filter, QWidget* widget);
+ void updateAutoSelectExtension() {};
+
+ //! Helper added because QFileDialog on win32 doesn't support ":" prefixes
+ //! for recent dir's storage.
+ QString realStartDir(const QString& startDir);
+
+ void saveLastVisitedPath(const QString& path);
+
+ QPushButton* m_okBtn;
+ QLineEdit* m_lineEdit;
+ QString m_lastVisitedPathsVariable; //!< Used by win32; @see realStartDir()
+ KexiStartupFileDialogBasePrivate* d;
+};
+
+#endif
diff --git a/kexi/main/startup/KexiStartupFileDialog_win.cpp b/kexi/main/startup/KexiStartupFileDialog_win.cpp
new file mode 100644
index 00000000..aa06fb9a
--- /dev/null
+++ b/kexi/main/startup/KexiStartupFileDialog_win.cpp
@@ -0,0 +1,476 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+/*!
+ Temporary moved from QKW KFileDialog implementation.
+ TODO: move to KDElibs/win32 KFileDialog wrapper
+*/
+
+#include "KexiStartupFileDialog.h"
+#include <kexiutils/utils.h>
+
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <krecentdirs.h>
+
+#include <qobjectlist.h>
+#include <qlineedit.h>
+
+#include <win/win32_utils.h>
+
+//! @internal
+class KexiStartupFileDialogBasePrivate
+{
+ public:
+ KexiStartupFileDialogBasePrivate()
+ {}
+ KFile::Mode mode;
+ QString kde_filters;
+ QStringList mimetypes;
+};
+
+KexiStartupFileDialogBase::KexiStartupFileDialogBase(
+ const QString & dirName, const QString & filter,
+ QWidget * parent, const char * name, bool modal )
+ : QFileDialog( realStartDir(dirName), filter, parent, name, modal )
+ , d(new KexiStartupFileDialogBasePrivate())
+{
+// QString _dirName = dirName;
+ QString _dirName = dirPath();
+ //make default 'My Documents' folder
+//TODO: store changes in the app's config file?
+ if (_dirName.isEmpty())
+ _dirName = KGlobalSettings::documentPath();
+
+ init(_dirName, filter, parent);
+
+ //find "OK" button
+ QObjectList *l = queryList( "QPushButton", "OK", false );
+ m_okBtn = dynamic_cast<QPushButton*>(l->first());
+ delete l;
+ l = queryList( "QLineEdit", "name/filter editor", false );
+ m_lineEdit = dynamic_cast<QLineEdit*>(l->first());
+ delete l;
+
+ adjustSize();
+}
+
+KexiStartupFileDialogBase::~KexiStartupFileDialogBase()
+{
+}
+
+void KexiStartupFileDialogBase::init(const QString& startDir, const QString& filter, QWidget* widget)
+{
+//TODO initStatic();
+//TODO d = new KFileDialogPrivate();
+
+//(js) d->boxLayout = 0;
+//TODO d->keepLocation = false;
+//TODO d->operationMode = Opening;
+ setMode(KFile::File | KFile::ExistingOnly); //(js) default: open action
+ setIcon( KGlobal::iconLoader()->loadIcon("fileopen", KIcon::Desktop) );
+ setDir(QDir(startDir));
+//TODO d->hasDefaultFilter = false;
+//TODO d->hasView = false;
+//(js) d->mainWidget = new QWidget( this, "KFileDialog::mainWidget");
+//(js) setMainWidget( d->mainWidget );
+//(js) d->okButton = new KPushButton( KStdGuiItem::ok(), d->mainWidget );
+//(js) d->okButton->setDefault( true );
+//(js) d->cancelButton = new KPushButton(KStdGuiItem::cancel(), d->mainWidget);
+//(js) connect( d->okButton, SIGNAL( clicked() ), SLOT( slotOk() ));
+//(js) connect( d->cancelButton, SIGNAL( clicked() ), SLOT( slotCancel() ));
+//(js) d->customWidget = widget;
+//(js) d->autoSelectExtCheckBox = 0; // delayed loading
+//TODO d->autoSelectExtChecked = false;
+//(js) d->urlBar = 0; // delayed loading
+//TODO KConfig *config = KGlobal::config();
+//TODO KConfigGroupSaver cs( config, ConfigGroup );
+//TODO d->initializeSpeedbar = config->readBoolEntry( "Set speedbar defaults",
+//TODO true );
+//TODO d->completionLock = false;
+
+//TODO QtMsgHandler oldHandler = qInstallMsgHandler( silenceQToolBar );
+//TODO toolbar = 0; //(js)
+//(js) toolbar = new KToolBar( d->mainWidget, "KFileDialog::toolbar", true);
+//(js) toolbar->setFlat(true);
+//TODO qInstallMsgHandler( oldHandler );
+
+//(js) d->pathCombo = new KURLComboBox( KURLComboBox::Directories, true,
+//(js) toolbar, "path combo" );
+//(js) QToolTip::add( d->pathCombo, i18n("Often used directories") );
+//(js) QWhatsThis::add( d->pathCombo, "<qt>" + i18n("Commonly used locations are listed here. "
+//(js) "This includes standard locations, such as your home directory, as well as "
+//(js) "locations that have been visited recently.") + autocompletionWhatsThisText);
+/*
+ KURL u;
+ u.setPath( QDir::rootDirPath() );
+ QString text = i18n("Root Directory: %1").arg( u.path() );
+ d->pathCombo->addDefaultURL( u,
+ KMimeType::pixmapForURL( u, 0, KIcon::Small ),
+ text );
+
+ u.setPath( QDir::homeDirPath() );
+ text = i18n("Home Directory: %1").arg( u.path( +1 ) );
+ d->pathCombo->addDefaultURL( u, KMimeType::pixmapForURL( u, 0, KIcon::Small ),
+ text );
+
+ KURL docPath;
+ docPath.setPath( KGlobalSettings::documentPath() );
+ if ( u.path(+1) != docPath.path(+1) ) {
+ text = i18n("Documents: %1").arg( docPath.path( +1 ) );
+ d->pathCombo->addDefaultURL( u,
+ KMimeType::pixmapForURL( u, 0, KIcon::Small ),
+ text );
+ }
+
+ u.setPath( KGlobalSettings::desktopPath() );
+ text = i18n("Desktop: %1").arg( u.path( +1 ) );
+ d->pathCombo->addDefaultURL( u,
+ KMimeType::pixmapForURL( u, 0, KIcon::Small ),
+ text );
+
+ u.setPath( "/tmp" );
+
+ d->url = getStartURL( startDir, d->fileClass );
+ d->selection = d->url.url();
+
+ // If local, check it exists. If not, go up until it exists.
+ if ( d->url.isLocalFile() )
+ {
+ if ( !QFile::exists( d->url.path() ) )
+ {
+ d->url = d->url.upURL();
+ QDir dir( d->url.path() );
+ while ( !dir.exists() )
+ {
+ d->url = d->url.upURL();
+ dir.setPath( d->url.path() );
+ }
+ }
+ }
+
+ ops = new KDirOperator(d->url, d->mainWidget, "KFileDialog::ops");
+ ops->setOnlyDoubleClickSelectsFiles( true );
+ connect(ops, SIGNAL(urlEntered(const KURL&)),
+ SLOT(urlEntered(const KURL&)));
+ connect(ops, SIGNAL(fileHighlighted(const KFileItem *)),
+ SLOT(fileHighlighted(const KFileItem *)));
+ connect(ops, SIGNAL(fileSelected(const KFileItem *)),
+ SLOT(fileSelected(const KFileItem *)));
+ connect(ops, SIGNAL(finishedLoading()),
+ SLOT(slotLoadingFinished()));
+
+ ops->setupMenu(KDirOperator::SortActions |
+ KDirOperator::FileActions |
+ KDirOperator::ViewActions);
+ KActionCollection *coll = ops->actionCollection();
+
+ // plug nav items into the toolbar
+ coll->action( "up" )->plug( toolbar );
+ coll->action( "up" )->setWhatsThis(i18n("<qt>Click this button to enter the parent directory.<p>"
+ "For instance, if the current location is file:/home/%1 clicking this "
+ "button will take you to file:/home.</qt>").arg(getlogin()));
+ coll->action( "back" )->plug( toolbar );
+ coll->action( "back" )->setWhatsThis(i18n("Click this button to move backwards one step in the browsing history."));
+ coll->action( "forward" )->plug( toolbar );
+ coll->action( "forward" )->setWhatsThis(i18n("Click this button to move forward one step in the browsing history."));
+ coll->action( "reload" )->plug( toolbar );
+ coll->action( "reload" )->setWhatsThis(i18n("Click this button to reload the contents of the current location."));
+ coll->action( "mkdir" )->setShortcut(Key_F10);
+ coll->action( "mkdir" )->plug( toolbar );
+ coll->action( "mkdir" )->setWhatsThis(i18n("Click this button to create a new directory."));
+
+ d->bookmarkHandler = new KFileBookmarkHandler( this );
+ toolbar->insertButton(QString::fromLatin1("bookmark"),
+ (int)HOTLIST_BUTTON, true,
+ i18n("Bookmarks"));
+ toolbar->getButton(HOTLIST_BUTTON)->setPopup( d->bookmarkHandler->menu(),
+ true);
+ QWhatsThis::add(toolbar->getButton(HOTLIST_BUTTON),
+ i18n("<qt>This button allows you to bookmark specific locations. "
+ "Click on this button to open the bookmark menu where you may add, "
+ "edit or select a bookmark.<p>"
+ "These bookmarks are specific to the file dialog, but otherwise operate "
+ "like bookmarks elsewhere in KDE.</qt>"));
+ connect( d->bookmarkHandler, SIGNAL( openURL( const QString& )),
+ SLOT( enterURL( const QString& )));
+
+ KToggleAction *showSidebarAction =
+ new KToggleAction(i18n("Show Quick Access Navigation Panel"), Key_F9, coll,"toggleSpeedbar");
+ connect( showSidebarAction, SIGNAL( toggled( bool ) ),
+ SLOT( toggleSpeedbar( bool )) );
+
+ KActionMenu *menu = new KActionMenu( i18n("Configure"), "configure", this, "extra menu" );
+ menu->setWhatsThis(i18n("<qt>This is the configuration menu for the file dialog. "
+ "Various options can be accessed from this menu including: <ul>"
+ "<li>how files are sorted in the list</li>"
+ "<li>types of view, including icon and list</li>"
+ "<li>showing of hidden files</li>"
+ "<li>the Quick Access navigation panel</li>"
+ "<li>file previews</li>"
+ "<li>separating directories from files</li></ul></qt>"));
+ menu->insert( coll->action( "sorting menu" ));
+ menu->insert( coll->action( "separator" ));
+ coll->action( "short view" )->setShortcut(Key_F6);
+ menu->insert( coll->action( "short view" ));
+ coll->action( "detailed view" )->setShortcut(Key_F7);
+ menu->insert( coll->action( "detailed view" ));
+ menu->insert( coll->action( "separator" ));
+ coll->action( "show hidden" )->setShortcut(Key_F8);
+ menu->insert( coll->action( "show hidden" ));
+ menu->insert( showSidebarAction );
+ coll->action( "preview" )->setShortcut(Key_F11);
+ menu->insert( coll->action( "preview" ));
+ coll->action( "separate dirs" )->setShortcut(Key_F12);
+ menu->insert( coll->action( "separate dirs" ));
+
+ menu->setDelayed( false );
+ connect( menu->popupMenu(), SIGNAL( aboutToShow() ),
+ ops, SLOT( updateSelectionDependentActions() ));
+ menu->plug( toolbar );
+*/
+ /*
+ * ugly little hack to have a 5 pixel space between the buttons
+ * and the combo box
+ */
+/* QWidget *spacerWidget = new QWidget(toolbar);
+//(js) spacerWidget->setMinimumWidth(spacingHint());
+//(js) spacerWidget->setMaximumWidth(spacingHint());
+ d->m_pathComboIndex = toolbar->insertWidget(-1, -1, spacerWidget);
+ toolbar->insertWidget(PATH_COMBO, 0, d->pathCombo);
+
+
+ toolbar->setItemAutoSized (PATH_COMBO);
+ toolbar->setIconText(KToolBar::IconOnly);
+ toolbar->setBarPos(KToolBar::Top);
+ toolbar->setMovingEnabled(false);
+ toolbar->adjustSize();
+
+ d->pathCombo->setCompletionObject( ops->dirCompletionObject(), false );
+
+ connect( d->pathCombo, SIGNAL( urlActivated( const KURL& )),
+ this, SLOT( enterURL( const KURL& ) ));
+ connect( d->pathCombo, SIGNAL( returnPressed( const QString& )),
+ this, SLOT( enterURL( const QString& ) ));
+ connect( d->pathCombo, SIGNAL(textChanged( const QString& )),
+ SLOT( pathComboChanged( const QString& ) ));
+ connect( d->pathCombo, SIGNAL( completion( const QString& )),
+ SLOT( dirCompletion( const QString& )));
+ connect( d->pathCombo, SIGNAL( textRotation(KCompletionBase::KeyBindingType) ),
+ d->pathCombo, SLOT( rotateText(KCompletionBase::KeyBindingType) ));
+
+ QString whatsThisText;
+
+ // the Location label/edit
+ d->locationLabel = new QLabel(i18n("&Location:"), d->mainWidget);
+ locationEdit = new KURLComboBox(KURLComboBox::Files, true,
+ d->mainWidget, "LocationEdit");
+ updateLocationWhatsThis ();
+ d->locationLabel->setBuddy(locationEdit);
+
+ // to get the completionbox-signals connected:
+ locationEdit->setHandleSignals( true );
+ (void) locationEdit->completionBox();
+
+ locationEdit->setFocus();
+// locationEdit->setCompletionObject( new KURLCompletion() );
+// locationEdit->setAutoDeleteCompletionObject( true );
+ locationEdit->setCompletionObject( ops->completionObject(), false );
+
+ connect( locationEdit, SIGNAL( returnPressed() ),
+ this, SLOT( slotOk()));
+ connect(locationEdit, SIGNAL( activated( const QString& )),
+ this, SLOT( locationActivated( const QString& ) ));
+ connect( locationEdit, SIGNAL( completion( const QString& )),
+ SLOT( fileCompletion( const QString& )));
+ connect( locationEdit, SIGNAL( textRotation(KCompletionBase::KeyBindingType) ),
+ locationEdit, SLOT( rotateText(KCompletionBase::KeyBindingType) ));
+
+ // the Filter label/edit
+ whatsThisText = i18n("<qt>This is the filter to apply to the file list. "
+ "File names that do not match the filter will not be shown.<p>"
+ "You may select from one of the preset filters in the "
+ "drop down menu, or you may enter a custom filter "
+ "directly into the text area.<p>"
+ "Wildcards such as * and ? are allowed.</qt>");
+ d->filterLabel = new QLabel(i18n("&Filter:"), d->mainWidget);
+ QWhatsThis::add(d->filterLabel, whatsThisText);
+ filterWidget = new KFileFilterCombo(d->mainWidget,
+ "KFileDialog::filterwidget");
+ QWhatsThis::add(filterWidget, whatsThisText);
+ setFilter(filter);
+ d->filterLabel->setBuddy(filterWidget);
+ connect(filterWidget, SIGNAL(filterChanged()), SLOT(slotFilterChanged()));
+
+ // the Automatically Select Extension checkbox
+ // (the text, visibility etc. is set in updateAutoSelectExtension(), which is called by readConfig())
+ d->autoSelectExtCheckBox = new QCheckBox (d->mainWidget);
+ connect(d->autoSelectExtCheckBox, SIGNAL(clicked()), SLOT(slotAutoSelectExtClicked()));
+
+ initGUI(); // activate GM
+
+ readRecentFiles( config );
+
+ adjustSize();
+
+ // we set the completionLock to avoid entering pathComboChanged() when
+ // inserting the list of URLs into the combo.
+ d->completionLock = true;
+ ops->setViewConfig( config, ConfigGroup );
+ readConfig( config, ConfigGroup );
+ setSelection(d->selection);
+ d->completionLock = false;
+ */
+}
+
+void KexiStartupFileDialogBase::clearFilter()
+{
+ d->kde_filters = "";//(js)
+ QFileDialog::setFilter(""); //(js);
+//todo d->mimetypes.clear();
+//todo d->hasDefaultFilter = false;
+
+ updateAutoSelectExtension ();
+}
+
+KFile::Mode KexiStartupFileDialogBase::mode() const
+{
+ return d->mode;
+}
+
+void KexiStartupFileDialogBase::setMode( KFile::Mode m )
+{
+ //(js) translate mode for QFileDialog
+ d->mode = m;
+ QFileDialog::Mode qm = (QFileDialog::Mode)0;
+ if (m & KFile::File) qm = Mode(qm | QFileDialog::AnyFile);
+ else if (m & KFile::Directory) qm = Mode(qm | QFileDialog::DirectoryOnly);
+ if (m & KFile::Files) qm = Mode(qm | QFileDialog::ExistingFiles);
+ if (m & KFile::ExistingOnly) qm = Mode(qm | QFileDialog::ExistingFile);
+
+ QFileDialog::setMode( qm );
+/*(js) ops->setMode(m);
+ if ( ops->dirOnlyMode() ) {
+//(js) filterWidget->setDefaultFilter( i18n("*|All Directories") );
+ }
+ else {
+//(js) filterWidget->setDefaultFilter( i18n("*|All Files") );
+ }
+
+ updateAutoSelectExtension ();*/
+}
+
+void KexiStartupFileDialogBase::setMode( unsigned int m )
+{
+ setMode(static_cast<KFile::Mode>( m ));
+}
+
+void KexiStartupFileDialogBase::setOperationMode( KFileDialog::OperationMode mode )
+{
+// d->operationMode = mode;
+ // d->keepLocation = (mode == Saving);
+ if (mode == KFileDialog::Saving) {
+ setMode( KFile::File );
+ setIcon( KGlobal::iconLoader()->loadIcon("filesave", KIcon::Desktop) );
+ }
+//(js) filterWidget->setEditable( !d->hasDefaultFilter || mode != Saving );
+//(js) d->okButton->setGuiItem( (mode == Saving) ? KStdGuiItem::save() : KStdGuiItem::ok() );
+//TODO updateLocationWhatsThis ();
+ updateAutoSelectExtension ();
+}
+
+QString KexiStartupFileDialogBase::currentFilter() const
+{
+ //(js)filterWidget->currentFilter();
+
+ //we need to convert Qt filter format to KDE format
+ //Qt format: "some text (*.first *.second)" or "All (*)"
+ //KDE format: "*.first *.second" or "*"
+ QString f = selectedFilter();
+ if (f.find('(')!=-1)
+ f = f.mid(f.find('(')+1);
+ if (f.mid(f.find(')')!=-1))
+ f = f.left(f.find(')'));
+ return f;
+}
+
+void KexiStartupFileDialogBase::setFilter(const QString& filter)
+{
+ d->kde_filters = filter;
+ int pos = d->kde_filters.find('/');
+
+ // Check for an un-escaped '/', if found
+ // interpret as a MIME filter.
+
+ if (pos > 0 && filter[pos - 1] != '\\') {
+ QStringList filters = QStringList::split( " ", d->kde_filters );
+ setMimeFilter( filters );
+ return;
+ }
+ QFileDialog::setFilters( convertKFileDialogFilterToQFileDialogFilter(filter) );
+ //</js>
+//(js) ops->clearFilter();
+//(js) filterWidget->setFilter(copy);
+//(js) ops->setNameFilter(filterWidget->currentFilter());
+//(js) d->hasDefaultFilter = false;
+//(js) filterWidget->setEditable( true );
+
+ updateAutoSelectExtension ();
+}
+
+void KexiStartupFileDialogBase::setMimeFilter( const QStringList& mimeTypes,
+ const QString& defaultType )
+{
+ d->mimetypes = mimeTypes;
+//(js) filterWidget->setMimeFilter( mimeTypes, defaultType );
+
+//(js) QStringList types = QStringList::split(" ", filterWidget->currentFilter());
+//(js) types.append( QString::fromLatin1( "inode/directory" ));
+//(js) ops->clearFilter();
+//(js) ops->setMimeFilter( types );
+//(js) d->hasDefaultFilter = !defaultType.isEmpty();
+//(js) filterWidget->setEditable( !d->hasDefaultFilter ||
+//(js) d->operationMode != Saving );
+
+//TODO updateAutoSelectExtension ();
+}
+
+QString KexiStartupFileDialogBase::realStartDir(const QString& startDir)
+{
+ if (!startDir.startsWith(":"))
+ return startDir;
+ QString recentDir; //dummy
+ QString path( KFileDialog::getStartURL(startDir, recentDir).path() );
+ if (path.isEmpty())
+ return QString::null;
+ QFileInfo fi(path);
+ return fi.isDir() ? fi.absFilePath() : fi.dir(true).absPath();
+}
+
+void KexiStartupFileDialogBase::saveLastVisitedPath(const QString& path)
+{
+ if (!m_lastVisitedPathsVariable.isEmpty()) {
+ //save last visited dir path
+// QString dir = QDir(path).absPath();
+ QFileInfo fi(path);
+ QString dir( fi.isDir() ? fi.absFilePath() : fi.dir(true).absPath() );
+ if (!dir.isEmpty())
+ KRecentDirs::add(m_lastVisitedPathsVariable, dir);
+ }
+}
diff --git a/kexi/main/startup/KexiStartup_p.cpp b/kexi/main/startup/KexiStartup_p.cpp
new file mode 100644
index 00000000..df7cddc6
--- /dev/null
+++ b/kexi/main/startup/KexiStartup_p.cpp
@@ -0,0 +1,127 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KexiStartup_p.h"
+
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <kprocess.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qapplication.h>
+
+SQLite2ToSQLite3Migration::SQLite2ToSQLite3Migration(const QString& filePath)
+: m_filePath(filePath)
+{
+ m_process = 0;
+ m_dlg = 0;
+ result = false;
+ m_run = false;
+}
+
+SQLite2ToSQLite3Migration::~SQLite2ToSQLite3Migration()
+{
+ delete m_process;
+ m_dlg->close();
+ delete m_dlg;
+}
+
+tristate SQLite2ToSQLite3Migration::run()
+{
+ if (m_run)
+ return false;
+ m_run = true;
+ const QString ksqlite2to3_app = KStandardDirs::findExe( "ksqlite2to3" );
+ if (ksqlite2to3_app.isEmpty())
+ return false;
+
+ QFileInfo fi(m_filePath);
+ if (fi.isSymLink()) {
+ m_filePath = fi.readLink();
+ fi = QFileInfo(m_filePath);
+ }
+ //remember permissions of m_filePath
+ m_restoreStat = (0==stat(QFile::encodeName(m_filePath), &m_st));
+
+ m_process = new KProcess(this, "process");
+ *m_process << ksqlite2to3_app << m_filePath;
+ m_process->setWorkingDirectory( fi.dir(true).absPath() );
+ connect( m_process, SIGNAL(receivedStderr(KProcess*,char*,int)),
+ this, SLOT(receivedStderr(KProcess*,char*,int)));
+ connect( m_process, SIGNAL(processExited(KProcess*)), this, SLOT(processExited(KProcess*)) );
+ if (!m_process->start(KProcess::NotifyOnExit, KProcess::Stderr))
+ return false;
+
+ m_dlg = new KProgressDialog(0, 0, QString::null,
+ i18n("Saving \"%1\" project file to a new \"%2\" database format...")
+ .arg(QDir::convertSeparators(QFileInfo(m_filePath).fileName())).arg("SQLite3")
+ );
+ m_dlg->setModal(true);
+ connect(m_dlg, SIGNAL(cancelClicked()), this, SLOT(cancelClicked()));
+ m_dlg->setMinimumDuration(1000);
+ m_dlg->setAutoClose(true);
+ m_dlg->progressBar()->setTotalSteps(100);
+ m_dlg->progressBar()->setProgress(0);
+ m_dlg->exec();
+
+ if (result!=true)
+ return result;
+
+ return result;
+}
+
+extern void updateProgressBar(KProgressDialog *pd, char *buffer, int buflen);
+
+void SQLite2ToSQLite3Migration::receivedStderr(KProcess *, char *buffer, int buflen)
+{
+ updateProgressBar(m_dlg, buffer, buflen);
+}
+
+void SQLite2ToSQLite3Migration::processExited(KProcess* process)
+{
+ kdDebug() << "EXIT " << process->name() << endl;
+
+ kdDebug() << process->isRunning() << " " << process->exitStatus() << endl;
+ m_dlg->close();
+ result = !process->isRunning() && 0==process->exitStatus();//m_process->normalExit();
+ kdDebug() << result.toString() << endl;
+ if (result == true) {
+ if (m_restoreStat) {
+ //restore permissions for m_filePath
+ chmod(QFile::encodeName(m_filePath), m_st.st_mode);
+ chown(QFile::encodeName(m_filePath), m_st.st_uid, m_st.st_gid);
+ }
+ }
+}
+
+void SQLite2ToSQLite3Migration::cancelClicked()
+{
+ kdDebug() << result.toString() << " cancelClicked() " <<m_process->isRunning() << " "
+ << m_process->exitStatus() << endl;
+ if (!m_process->isRunning() && 0==m_process->exitStatus())
+ return;
+ result = cancelled;
+ m_process->kill();
+}
+
+#include "KexiStartup_p.moc"
+
diff --git a/kexi/main/startup/KexiStartup_p.h b/kexi/main/startup/KexiStartup_p.h
new file mode 100644
index 00000000..1e60d702
--- /dev/null
+++ b/kexi/main/startup/KexiStartup_p.h
@@ -0,0 +1,59 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEXI_STARTUPHANDLER_P_H
+#define KEXI_STARTUPHANDLER_P_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <sys/stat.h>
+
+#include <kexiutils/tristate.h>
+
+class KProcess;
+class KProgressDialog;
+
+class SQLite2ToSQLite3Migration : public QObject
+{
+ Q_OBJECT
+ public:
+ SQLite2ToSQLite3Migration(const QString& filePath);
+ ~SQLite2ToSQLite3Migration();
+
+ tristate run();
+
+ public slots:
+ void processExited(KProcess*);
+ void receivedStderr(KProcess*,char*,int);
+ void cancelClicked();
+
+ protected:
+ QString m_filePath;
+ KProcess *m_process;
+ KProgressDialog* m_dlg;
+
+ struct stat m_st;
+ bool m_restoreStat : 1;
+ bool m_run : 1;
+
+ tristate result;
+};
+
+#endif
diff --git a/kexi/main/startup/Makefile.am b/kexi/main/startup/Makefile.am
new file mode 100644
index 00000000..a7f2f30e
--- /dev/null
+++ b/kexi/main/startup/Makefile.am
@@ -0,0 +1,47 @@
+include $(top_srcdir)/kexi/Makefile.global
+
+noinst_LTLIBRARIES = libkeximainstartup.la
+
+libkeximainstartup_la_SOURCES = KexiConnSelectorBase.ui KexiProjectSelectorBase.ui \
+ KexiOpenExistingFile.ui \
+ KexiNewPrjTypeSelector.ui KexiDBTitlePageBase.ui \
+ KexiServerDBNamePage.ui \
+ KexiDBTitlePage.cpp \
+ KexiConnSelector.cpp KexiProjectSelector.cpp \
+ KexiStartupDialog.cpp \
+ KexiStartupFileDialog.cpp KexiNewProjectWizard.cpp \
+ KexiStartup.cpp KexiStartup_p.cpp KexiStartupDialogTemplatesPage.cpp
+
+noinst_HEADERS = KexiStartup_p.h
+
+libkeximainstartup_la_LDFLAGS = $(all_libraries) -Wnounresolved
+libkeximainstartup_la_LIBADD = \
+ ../../widget/libkexiextendedwidgets.la
+
+libkeximainstartup_la_METASOURCES = AUTO
+
+SUBDIRS = .
+
+# kde_appsdir Where your application's menu entry (.desktop) should go to.
+# kde_icondir Where your icon should go to - better use KDE_ICON.
+# kde_sounddir Where your sounds should go to.
+# kde_htmldir Where your docs should go to. (contains lang subdirs)
+# kde_datadir Where you install application data. (Use a subdir)
+# kde_locale Where translation files should go to. (contains lang subdirs)
+# kde_cgidir Where cgi-bin executables should go to.
+# kde_confdir Where config files should go to (system-wide ones with default values).
+# kde_mimedir Where mimetypes .desktop files should go to.
+# kde_servicesdir Where services .desktop files should go to.
+# kde_servicetypesdir Where servicetypes .desktop files should go to.
+# kde_toolbardir Where general toolbar icons should go to (deprecated, use KDE_ICON).
+# kde_wallpaperdir Where general wallpapers should go to.
+# kde_templatesdir Where templates for the "New" menu (Konqueror/KDesktop) should go to.
+# kde_bindir Where executables should go to. Use bin_PROGRAMS or bin_SCRIPTS.
+# kde_libdir Where shared libraries should go to. Use lib_LTLIBRARIES.
+# kde_moduledir Where modules (e.g. parts) should go to. Use kde_module_LTLIBRARIES.
+# kde_styledir Where Qt/KDE widget styles should go to (new in KDE 3).
+# kde_designerdir Where Qt Designer plugins should go to (new in KDE 3).
+
+# set the include path for X, qt and KDE
+INCLUDES= -I$(top_srcdir)/kexi -I$(top_srcdir)/kexi/main/startup -I$(top_srcdir)/kexi/core -I$(top_srcdir)/kexi/widget -I$(top_builddir)/kexi/widget $(all_includes)
+