/* This file is part of the KDE project Copyright (C) 2003 Lucijan Busch Copyright (C) 2003-2005 Jaroslaw Staniek 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 "kexipart.h" #include "kexipartinfo.h" #include "kexipartitem.h" #include "kexistaticpart.h" #include "kexidialogbase.h" #include "kexiviewbase.h" #include "kexipartguiclient.h" #include "keximainwindow.h" //#include "kexipartdatasource.h" #include "kexi.h" #include #include #include #include #include #include #include namespace KexiPart { //! @internal class PartPrivate { public: PartPrivate() : instanceActionsInitialized(false) { } //! Helper, used in Part::openInstance() tristate askForOpeningInTextMode(KexiDialogBase *dlg, KexiPart::Item &item, int supportedViewModes, int viewMode) { if (viewMode != Kexi::TextViewMode && supportedViewModes & Kexi::TextViewMode && dlg->tempData()->proposeOpeningInTextViewModeBecauseOfProblems) { //ask KexiUtils::WaitCursorRemover remover; //! @todo use message handler for this to enable non-gui apps TQString singleStatusString( dlg->singleStatusString() ); if (!singleStatusString.isEmpty()) singleStatusString.prepend(TQString("\n\n")+i18n("Details:")+" "); if (KMessageBox::No==KMessageBox::questionYesNo(0, ((viewMode == Kexi::DesignViewMode) ? i18n("Object \"%1\" could not be opened in Design View.").arg(item.name()) : i18n("Object could not be opened in Data View."))+"\n" + i18n("Do you want to open it in Text View?") + singleStatusString, 0, KStdGuiItem::open(), KStdGuiItem::cancel())) { // dlg->close(); //this will destroy dlg return false; } return true; } return cancelled; } bool instanceActionsInitialized : 1; }; } //---------------------------------------------------------------- using namespace KexiPart; Part::Part(TQObject *parent, const char *name, const TQStringList &) : TQObject(parent, name) , m_guiClient(0) , m_registeredPartID(-1) //no registered ID by default , d(new PartPrivate()) { m_info = 0; m_supportedViewModes = Kexi::DataViewMode | Kexi::DesignViewMode; m_supportedUserViewModes = Kexi::DataViewMode; m_mainWin = 0; m_newObjectsAreDirty = false; } Part::Part(TQObject* parent, StaticInfo *info) : TQObject(parent, "StaticPart") , m_guiClient(0) , m_registeredPartID(-1) //no registered ID by default , d(new PartPrivate()) { m_info = info; m_supportedViewModes = Kexi::DesignViewMode; m_supportedUserViewModes = 0; m_mainWin = 0; m_newObjectsAreDirty = false; } Part::~Part() { delete d; } void Part::createGUIClients(KexiMainWindow *win) { m_mainWin = win; if (!m_guiClient) { //create part's gui client m_guiClient = new GUIClient(m_mainWin, this, false, "part"); //default actions for part's gui client: TDEAction *act = new TDEAction(m_names["instanceCaption"]+"...", info()->createItemIcon(), 0, this, TQT_SLOT(slotCreate()), m_mainWin->actionCollection(), KexiPart::nameForCreateAction(*info())); act->plug( m_mainWin->findPopupMenu("insert") ); // new TDEAction(m_names["instance"]+"...", info()->itemIcon(), 0, this, // TQT_SLOT(create()), m_guiClient->actionCollection(), (info()->objectName()+"part_create").latin1()); //let init specific actions for parts // initPartActions( m_guiClient->actionCollection() ); m_mainWin->guiFactory()->addClient(m_guiClient); //this client is added permanently //create part instance's gui client // m_instanceGuiClient = new GUIClient(win, this, true); //default actions for part instance's gui client: //NONE //let init specific actions for part instances for (int mode = 1; mode <= 0x01000; mode <<= 1) { if (m_supportedViewModes & mode) { GUIClient *instanceGuiClient = new GUIClient(m_mainWin, this, true, Kexi::nameForViewMode(mode).latin1()); m_instanceGuiClients.insert(mode, instanceGuiClient); // initInstanceActions( mode, instanceGuiClient->actionCollection() ); } } // also add an instance common for all modes (mode==0) GUIClient *instanceGuiClient = new GUIClient(m_mainWin, this, true, "allViews"); m_instanceGuiClients.insert(Kexi::AllViewModes, instanceGuiClient); // initInstanceActions( Kexi::AllViewModes , instanceGuiClient->actionCollection() ); //todo initPartActions(); // initActions(); } } TDEActionCollection* Part::actionCollectionForMode(int viewMode) const { KXMLGUIClient *cli = m_instanceGuiClients[viewMode]; return cli ? cli->actionCollection() : 0; } TDEAction* Part::createSharedAction(int mode, const TQString &text, const TQString &pix_name, const TDEShortcut &cut, const char *name, const char *subclassName) { GUIClient *instanceGuiClient = m_instanceGuiClients[mode]; if (!instanceGuiClient) { kdDebug() << "KexiPart::createSharedAction(): no gui client for mode " << mode << "!" << endl; return 0; } return m_mainWin->createSharedAction(text, pix_name, cut, name, instanceGuiClient->actionCollection(), subclassName); } TDEAction* Part::createSharedPartAction(const TQString &text, const TQString &pix_name, const TDEShortcut &cut, const char *name, const char *subclassName) { if (!m_guiClient) return 0; return m_mainWin->createSharedAction(text, pix_name, cut, name, m_guiClient->actionCollection(), subclassName); } TDEAction* Part::createSharedToggleAction(int mode, const TQString &text, const TQString &pix_name, const TDEShortcut &cut, const char *name) { return createSharedAction(mode, text, pix_name, cut, name, "TDEToggleAction"); } TDEAction* Part::createSharedPartToggleAction(const TQString &text, const TQString &pix_name, const TDEShortcut &cut, const char *name) { return createSharedPartAction(text, pix_name, cut, name, "TDEToggleAction"); } /*TDEAction* Part::sharedAction(int mode, const char* name, const char *classname) { GUIClient *instanceGuiClient = m_instanceGuiClients[mode]; if (!instanceGuiClient) { kdDebug() << "KexiPart::createSharedAction(): no gui client for mode " << mode << "!" << endl; return 0; } return instanceGuiClient->actionCollection()->action(name, classname); } TDEAction* Part::sharedPartAction(int mode, const char* name, const char *classname) { if (!m_guiClient) return 0; return m_guiClient->actionCollection()->action(name, classname); }*/ void Part::setActionAvailable(const char *action_name, bool avail) { TQIntDictIterator it( m_instanceGuiClients ); for (;it.current();++it) { TDEAction *act = it.current()->actionCollection()->action(action_name); if (act) { act->setEnabled(avail); return; } } m_mainWin->setActionAvailable(action_name, avail); } KexiDialogBase* Part::openInstance(KexiMainWindow *win, KexiPart::Item &item, int viewMode, TQMap* staticObjectArgs) { //now it's the time for creating instance actions if (!d->instanceActionsInitialized) { initInstanceActions(); d->instanceActionsInitialized = true; } m_status.clearStatus(); // KexiDialogBase *dlg = createInstance(win,item,viewMode); // if (!dlg) // return 0; // TQString capt = TQString("%1 : %2").arg(item.name()).arg(instanceName()); KexiDialogBase *dlg = new KexiDialogBase(win); dlg->m_supportedViewModes = m_supportedViewModes; // dlg->m_neverSaved = item.neverSaved(); // dlg->m_currentViewMode = viewMode; dlg->m_part = this; dlg->m_item = &item; dlg->updateCaption(); KexiDB::SchemaData sdata(m_info->projectPartID()); sdata.setName( item.name() ); sdata.setCaption( item.caption() ); sdata.setDescription( item.description() ); /*! @todo js: apply settings for caption displaying method; there can be option for - displaying item.caption() as caption, if not empty, without instanceName - displaying the same as above in tabCaption (or not) */ // dlg->setCaption( capt ); // dlg->setTabCaption( item.name() ); dlg->setId(item.identifier()); //not needed, but we did it //moved down dlg->registerDialog(); dlg->setIcon( SmallIcon( dlg->itemIcon() ) ); if (dlg->mdiParent()) dlg->mdiParent()->setIcon( *dlg->icon() ); // if (dlg->mainWidget()) // dlg->mainWidget()->setIcon( *dlg->icon() ); dlg->stack()->setIcon( *dlg->icon() ); dlg->m_tempData = createTempData(dlg); if (!item.neverSaved()) { //we have to load schema data for this dialog dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode); if (!dlg->m_schemaData) { //last chance: if (false == d->askForOpeningInTextMode(dlg, item, dlg->m_supportedViewModes, viewMode)) { delete dlg; return 0; } viewMode = Kexi::TextViewMode; dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode); } if (!dlg->m_schemaData) { if (!m_status.error()) m_status = Kexi::ObjectStatus( dlg->mainWin()->project()->dbConnection(), i18n("Could not load object's definition."), i18n("Object design may be corrupted.")); m_status.append( Kexi::ObjectStatus(i18n("You can delete \"%1\" object and create it again.") .arg(item.name()), TQString()) ); dlg->close(); delete dlg; return 0; } } bool switchingFailed = false; bool dummy; tristate res = dlg->switchToViewMode( viewMode, staticObjectArgs, dummy ); if (!res) { tristate askForOpeningInTextModeRes = d->askForOpeningInTextMode(dlg, item, dlg->m_supportedViewModes, viewMode); // if (viewMode==Kexi::DesignViewMode && dlg->isDesignModePreloadedForTextModeHackUsed(Kexi::TextViewMode)) // askForOpeningInTextModeRes = cancelled; //do not try // else if (true == askForOpeningInTextModeRes) { delete dlg->m_schemaData; //old one dlg->close(); delete dlg; //try in text mode return openInstance(win, item, Kexi::TextViewMode, staticObjectArgs); } else if (false == askForOpeningInTextModeRes) { delete dlg->m_schemaData; //old one dlg->close(); delete dlg; return 0; } //dlg has an error info switchingFailed = true; } if (~res) switchingFailed = true; if (switchingFailed) { m_status = dlg->status(); dlg->close(); delete dlg; return 0; } dlg->registerDialog(); //ok? dlg->show(); if (dlg->mdiParent() && dlg->mdiParent()->state()==KMdiChildFrm::Normal) //only resize dialog if it is in normal state dlg->resize(dlg->sizeHint()); dlg->setMinimumSize(dlg->minimumSizeHint().width(),dlg->minimumSizeHint().height()); //dirty only if it's a new object if (dlg->selectedView()) dlg->selectedView()->setDirty( m_newObjectsAreDirty ? item.neverSaved() : false ); return dlg; } void Part::slotCreate() { emit newObjectRequest( m_info ); } KexiDB::SchemaData* Part::loadSchemaData(KexiDialogBase * /*dlg*/, const KexiDB::SchemaData& sdata, int /*viewMode*/) { KexiDB::SchemaData *new_schema = new KexiDB::SchemaData(); *new_schema = sdata; return new_schema; } bool Part::loadDataBlock( KexiDialogBase *dlg, TQString &dataString, const TQString& dataID) { if (!dlg->mainWin()->project()->dbConnection()->loadDataBlock( dlg->id(), dataString, dataID )) { m_status = Kexi::ObjectStatus( dlg->mainWin()->project()->dbConnection(), i18n("Could not load object's data."), i18n("Data identifier: \"%1\".").arg(dataID) ); m_status.append( *dlg ); return false; } return true; } void Part::initPartActions() { } void Part::initInstanceActions() { } bool Part::remove(KexiMainWindow *win, KexiPart::Item &item) { if (!win || !win->project() || !win->project()->dbConnection()) return false; KexiDB::Connection *conn = win->project()->dbConnection(); return conn->removeObject( item.identifier() ); } KexiDialogTempData* Part::createTempData(KexiDialogBase* dialog) { return new KexiDialogTempData(dialog); } TQString Part::i18nMessage(const TQCString& englishMessage, KexiDialogBase* dlg) const { Q_UNUSED(dlg); return TQString(englishMessage).startsWith(":") ? TQString() : englishMessage; } void Part::setupCustomPropertyPanelTabs(KTabWidget *, KexiMainWindow*) { } TQCString Part::instanceName() const { // "instanceName" should be already valid identifier but we're using // KexiUtils::string2Identifier() to be sure translators did it right. return KexiUtils::string2Identifier(m_names["instanceName"]).lower().latin1(); } TQString Part::instanceCaption() const { return m_names["instanceCaption"]; } tristate Part::rename(KexiMainWindow *win, KexiPart::Item &item, const TQString& newName) { Q_UNUSED(win); Q_UNUSED(item); Q_UNUSED(newName); return true; } //------------------------------------------------------------------------- GUIClient::GUIClient(KexiMainWindow *win, Part* part, bool partInstanceClient, const char* nameSuffix) : TQObject(part, (part->info()->objectName() + (nameSuffix ? TQString(":%1").arg(nameSuffix) : TQString())).latin1() ) , KXMLGUIClient(win) { if(!win->project()->data()->userMode()) setXMLFile(TQString::fromLatin1("kexi")+part->info()->objectName() +"part"+(partInstanceClient?"inst":"")+"ui.rc"); // new TDEAction(part->m_names["new"], part->info()->itemIcon(), 0, this, // TQT_SLOT(create()), actionCollection(), (part->info()->objectName()+"part_create").latin1()); // new TDEAction(i18nInstanceName+"...", part->info()->itemIcon(), 0, this, // TQT_SLOT(create()), actionCollection(), (part->info()->objectName()+"part_create").latin1()); // win->guiFactory()->addClient(this); } #include "kexipart.moc"