diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/main/startup | |
download | koffice-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/startup')
27 files changed, 5992 insertions, 0 deletions
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>&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>&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>&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><b>Select Existing Database Server's Connection From the List Below</b> +<p>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><b>Select existing Kexi project file to open:</b> +</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>&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><b>There are Kexi projects you have recently opened.</b> 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) + |