kexi

kexipart.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
00003    Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kexipart.h"
00022 #include "kexipartinfo.h"
00023 #include "kexipartitem.h"
00024 #include "kexistaticpart.h"
00025 #include "kexidialogbase.h"
00026 #include "kexiviewbase.h"
00027 
00028 #include "kexipartguiclient.h"
00029 #include "keximainwindow.h"
00030 //#include "kexipartdatasource.h"
00031 #include "kexi.h"
00032 
00033 #include <kexidb/connection.h>
00034 #include <kexiutils/identifier.h>
00035 #include <kexiutils/utils.h>
00036 
00037 #include <qwidgetstack.h>
00038 
00039 #include <kiconloader.h>
00040 #include <kdebug.h>
00041 #include <kmessagebox.h>
00042 
00043 namespace KexiPart {
00045 class PartPrivate
00046 {
00047 public:
00048     PartPrivate()
00049     : instanceActionsInitialized(false)
00050     {
00051     }
00052     bool instanceActionsInitialized : 1;
00053 };
00054 }
00055 
00056 //----------------------------------------------------------------
00057 
00058 using namespace KexiPart;
00059 
00060 Part::Part(QObject *parent, const char *name, const QStringList &)
00061 : QObject(parent, name)
00062 , m_guiClient(0)
00063 , m_registeredPartID(-1) //no registered ID by default
00064 , d(new PartPrivate())
00065 {
00066     m_info = 0;
00067     m_supportedViewModes = Kexi::DataViewMode | Kexi::DesignViewMode;
00068     m_mainWin = 0;
00069     m_newObjectsAreDirty = false;
00070 }
00071 
00072 Part::Part(QObject* parent, StaticInfo *info)
00073 : QObject(parent, "StaticPart")
00074 , m_guiClient(0)
00075 , m_registeredPartID(-1) //no registered ID by default
00076 , d(new PartPrivate())
00077 {
00078     m_info = info;
00079     m_supportedViewModes = Kexi::DesignViewMode;
00080     m_mainWin = 0;
00081     m_newObjectsAreDirty = false;
00082 }
00083 
00084 Part::~Part()
00085 {
00086     delete d;
00087 }
00088 
00089 void Part::createGUIClients(KexiMainWindow *win)
00090 {
00091     m_mainWin = win;
00092     if (!m_guiClient) {
00093         //create part's gui client
00094         m_guiClient = new GUIClient(m_mainWin, this, false);
00095 
00096         //default actions for part's gui client:
00097         KAction *act = new KAction(m_names["instanceCaption"]+"...", info()->createItemIcon(), 0, this, 
00098             SLOT(slotCreate()), m_mainWin->actionCollection(), 
00099             KexiPart::nameForCreateAction(*info()));
00100         act->plug( m_mainWin->findPopupMenu("insert") );
00101 //      new KAction(m_names["instance"]+"...", info()->itemIcon(), 0, this, 
00102 //      SLOT(create()), m_guiClient->actionCollection(), (info()->objectName()+"part_create").latin1());
00103         //let init specific actions for parts
00104 //      initPartActions( m_guiClient->actionCollection() );
00105         m_mainWin->guiFactory()->addClient(m_guiClient); //this client is added permanently
00106 
00107         //create part instance's gui client
00108 //      m_instanceGuiClient = new GUIClient(win, this, true);
00109 
00110         //default actions for part instance's gui client:
00111         //NONE
00112         //let init specific actions for part instances
00113         for (int mode = 1; mode <= 0x01000; mode <<= 1) {
00114             if (m_supportedViewModes & mode) {
00115                 GUIClient *instanceGuiClient = new GUIClient(m_mainWin, this, true);
00116                 m_instanceGuiClients.insert(mode, instanceGuiClient);
00117 //              initInstanceActions( mode, instanceGuiClient->actionCollection() );
00118             }
00119         }
00120         // also add an instance common for all modes (mode==0)
00121         GUIClient *instanceGuiClient = new GUIClient(m_mainWin, this, true);
00122         m_instanceGuiClients.insert(Kexi::AllViewModes, instanceGuiClient);
00123 //      initInstanceActions( Kexi::AllViewModes , instanceGuiClient->actionCollection() );
00124 
00125 //todo
00126         initPartActions();
00127 //      initActions();
00128     }
00129 }
00130 
00131 KActionCollection* Part::actionCollectionForMode(int viewMode) const
00132 {
00133     KXMLGUIClient *cli = m_instanceGuiClients[viewMode];
00134     return cli ? cli->actionCollection() : 0;
00135 }
00136 
00137 KAction* Part::createSharedAction(int mode, const QString &text, 
00138     const QString &pix_name, const KShortcut &cut, const char *name,
00139     const char *subclassName)
00140 {
00141     GUIClient *instanceGuiClient = m_instanceGuiClients[mode];
00142     if (!instanceGuiClient) {
00143         kdDebug() << "KexiPart::createSharedAction(): no gui client for mode " << mode << "!" << endl;
00144         return 0;
00145     }
00146     return m_mainWin->createSharedAction(text, pix_name, cut, name, 
00147         instanceGuiClient->actionCollection(), subclassName);
00148 }
00149 
00150 KAction* Part::createSharedPartAction(const QString &text, 
00151     const QString &pix_name, const KShortcut &cut, const char *name,
00152     const char *subclassName)
00153 {
00154     if (!m_guiClient)
00155         return 0;
00156     return m_mainWin->createSharedAction(text, pix_name, cut, name, 
00157         m_guiClient->actionCollection(), subclassName);
00158 }
00159 
00160 KAction* Part::createSharedToggleAction(int mode, const QString &text, 
00161     const QString &pix_name, const KShortcut &cut, const char *name)
00162 {
00163     return createSharedAction(mode, text, pix_name, cut, name, "KToggleAction");
00164 }
00165 
00166 KAction* Part::createSharedPartToggleAction(const QString &text, 
00167     const QString &pix_name, const KShortcut &cut, const char *name)
00168 {
00169     return createSharedPartAction(text, pix_name, cut, name, "KToggleAction");
00170 }
00171 
00172 /*KAction* Part::sharedAction(int mode, const char* name, const char *classname)
00173 {
00174     GUIClient *instanceGuiClient = m_instanceGuiClients[mode];
00175     if (!instanceGuiClient) {
00176         kdDebug() << "KexiPart::createSharedAction(): no gui client for mode " << mode << "!" << endl;
00177         return 0;
00178     }
00179     return instanceGuiClient->actionCollection()->action(name, classname);
00180 }
00181 
00182 KAction* Part::sharedPartAction(int mode, const char* name, const char *classname)
00183 {
00184     if (!m_guiClient)
00185         return 0;
00186     return m_guiClient->actionCollection()->action(name, classname);
00187 }*/
00188 
00189 void Part::setActionAvailable(const char *action_name, bool avail)
00190 {
00191     QIntDictIterator<GUIClient> it( m_instanceGuiClients );
00192     for (;it.current();++it) {
00193         KAction *act = it.current()->actionCollection()->action(action_name);
00194         if (act) {
00195             act->setEnabled(avail);
00196             return;
00197         }
00198     }
00199 
00200     m_mainWin->setActionAvailable(action_name, avail);
00201 }
00202 
00203 KexiDialogBase* Part::openInstance(KexiMainWindow *win, KexiPart::Item &item, int viewMode,
00204     QMap<QString,QString>* staticObjectArgs)
00205 {
00206     //now it's the time for creating instance actions
00207     if (!d->instanceActionsInitialized) {
00208         initInstanceActions();
00209         d->instanceActionsInitialized = true;
00210     }
00211 
00212     m_status.clearStatus();
00213 //  KexiDialogBase *dlg = createInstance(win,item,viewMode);
00214 //  if (!dlg)
00215 //      return 0;
00216 //  QString capt = QString("%1 : %2").arg(item.name()).arg(instanceName());
00217     KexiDialogBase *dlg = new KexiDialogBase(win);
00218     dlg->m_supportedViewModes = m_supportedViewModes;
00219 //  dlg->m_neverSaved = item.neverSaved();
00220 //  dlg->m_currentViewMode = viewMode;
00221     dlg->m_part = this;
00222     dlg->m_item = &item;
00223     dlg->updateCaption();
00224 
00225     KexiDB::SchemaData sdata(m_info->projectPartID());
00226     sdata.setName( item.name() );
00227     sdata.setCaption( item.caption() );
00228     sdata.setDescription( item.description() );
00229 
00233 //  dlg->setCaption( capt );
00234 //  dlg->setTabCaption( item.name() );
00235     dlg->setId(item.identifier()); //not needed, but we did it
00236 //moved down    dlg->registerDialog();
00237     dlg->setIcon( SmallIcon( dlg->itemIcon() ) );
00238     if (dlg->mdiParent())
00239         dlg->mdiParent()->setIcon( *dlg->icon() );
00240 //  if (dlg->mainWidget())
00241 //      dlg->mainWidget()->setIcon( *dlg->icon() );
00242     dlg->stack()->setIcon( *dlg->icon() );
00243     dlg->m_tempData = createTempData(dlg);
00244 
00245     if (!item.neverSaved()) {
00246         //we have to load schema data for this dialog
00247         dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode);
00248         if (!dlg->m_schemaData) {
00249             //last chance:
00250             if (viewMode != Kexi::TextViewMode
00251                 && dlg->m_supportedViewModes & Kexi::TextViewMode 
00252                 && dlg->tempData()->proposeOpeningInTextViewModeBecauseOfProblems)
00253             {
00254                 //ask
00255                 KexiUtils::removeWaitCursor();
00257                 if (KMessageBox::No==KMessageBox::questionYesNo(0, 
00258                     ((viewMode == Kexi::DesignViewMode) 
00259                      ? i18n("Object \"%1\" could not be opened in Design View.").arg(item.name())
00260                      : i18n("Object could not be opened in Data View."))+"\n"
00261                     + i18n("Do you want to open it in Text View?"), 0, 
00262                     KStdGuiItem::open(), KStdGuiItem::cancel()))
00263                 {
00264 //                  dlg->close(); //this will destroy dlg
00265                     delete dlg;
00266                     return 0;
00267                 }
00268                 viewMode = Kexi::TextViewMode;
00269                 dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode);
00270             }
00271         }
00272         if (!dlg->m_schemaData) {
00273             if (!m_status.error())
00274                 m_status = Kexi::ObjectStatus( dlg->mainWin()->project()->dbConnection(), 
00275                     i18n("Could not load object's definition."), i18n("Object design may be corrupted."));
00276             m_status.append( 
00277                 Kexi::ObjectStatus(i18n("You can delete \"%1\" object and create it again.")
00278                 .arg(item.name()), QString::null) );
00279 
00280             dlg->close();
00281             delete dlg;
00282             return 0;
00283         }
00284     }
00285 
00286     bool switchingFailed = false;
00287     tristate res = dlg->switchToViewMode( viewMode, staticObjectArgs );
00288     if (!res) {
00289         //dlg has an error info
00290         switchingFailed = true;
00291     }
00292     if (~res)
00293         switchingFailed = true;
00294 
00295     if (switchingFailed) {
00296         m_status = dlg->status();
00297         dlg->close();
00298         delete dlg;
00299         return 0;
00300     }
00301     dlg->registerDialog(); //ok?
00302     dlg->show();
00303 
00304     if (dlg->mdiParent() && dlg->mdiParent()->state()==KMdiChildFrm::Normal) //only resize dialog if it is in normal state
00305         dlg->resize(dlg->sizeHint());
00306 
00307     dlg->setMinimumSize(dlg->minimumSizeHint().width(),dlg->minimumSizeHint().height());
00308 
00309     //dirty only if it's a new object
00310     if (dlg->selectedView())
00311         dlg->selectedView()->setDirty( m_newObjectsAreDirty ? item.neverSaved() : false );
00312     
00313     return dlg;
00314 }
00315 
00316 void Part::slotCreate()
00317 {
00318     emit newObjectRequest( m_info );
00319 }
00320 
00321 KexiDB::SchemaData* Part::loadSchemaData(KexiDialogBase * /*dlg*/, const KexiDB::SchemaData& sdata, 
00322     int /*viewMode*/)
00323 {
00324     KexiDB::SchemaData *new_schema = new KexiDB::SchemaData();
00325     *new_schema = sdata;
00326     return new_schema;
00327 }
00328 
00329 bool Part::loadDataBlock( KexiDialogBase *dlg, QString &dataString, const QString& dataID)
00330 {
00331     if (!dlg->mainWin()->project()->dbConnection()->loadDataBlock( dlg->id(), dataString, dataID )) {
00332         m_status = Kexi::ObjectStatus( dlg->mainWin()->project()->dbConnection(), 
00333             i18n("Could not load object's data."), i18n("Data identifier: \"%1\".").arg(dataID) );
00334         m_status.append( *dlg );
00335         return false;
00336     }
00337     return true;
00338 }
00339 
00340 void Part::initPartActions()
00341 {
00342 }
00343 
00344 void Part::initInstanceActions()
00345 {
00346 }
00347 
00348 bool Part::remove(KexiMainWindow *win, KexiPart::Item &item)
00349 {
00350     if (!win || !win->project() || !win->project()->dbConnection())
00351         return false;
00352     KexiDB::Connection *conn = win->project()->dbConnection();
00353     return conn->removeObject( item.identifier() );
00354 }
00355 
00356 KexiDialogTempData* Part::createTempData(KexiDialogBase* dialog)
00357 {
00358     return new KexiDialogTempData(dialog);
00359 }
00360 
00361 QString Part::i18nMessage(const QCString& englishMessage, KexiDialogBase* dlg) const
00362 {
00363     Q_UNUSED(dlg);
00364     return QString(englishMessage).startsWith(":") ? QString::null : englishMessage;
00365 }
00366 
00367 void Part::setupCustomPropertyPanelTabs(KTabWidget *, KexiMainWindow*)
00368 {
00369 }
00370 
00371 QCString Part::instanceName() const
00372 {
00373     // "instanceName" should be already valid identifier but we're using
00374     // KexiUtils::string2Identifier() to be sure translators did it right.
00375     return KexiUtils::string2Identifier(m_names["instanceName"]).lower().latin1();
00376 }
00377 
00378 QString Part::instanceCaption() const
00379 {
00380     return m_names["instanceCaption"];
00381 }
00382 
00383 tristate Part::rename(KexiMainWindow *win, KexiPart::Item &item, const QString& newName)
00384 {
00385     Q_UNUSED(win);
00386     Q_UNUSED(item);
00387     Q_UNUSED(newName);
00388     return true;
00389 }
00390 
00391 //-------------------------------------------------------------------------
00392 
00393 
00394 GUIClient::GUIClient(KexiMainWindow *win, Part* part, bool partInstanceClient)
00395  : QObject(part, part->info()->objectName().latin1()), KXMLGUIClient(win)
00396 {
00397     if(!win->project()->final())
00398         setXMLFile(QString::fromLatin1("kexi")+part->info()->objectName()
00399             +"part"+(partInstanceClient?"inst":"")+"ui.rc");
00400 
00401 //  new KAction(part->m_names["new"], part->info()->itemIcon(), 0, this, 
00402 //      SLOT(create()), actionCollection(), (part->info()->objectName()+"part_create").latin1());
00403 
00404 //  new KAction(i18nInstanceName+"...", part->info()->itemIcon(), 0, this, 
00405 //      SLOT(create()), actionCollection(), (part->info()->objectName()+"part_create").latin1());
00406 
00407 //  win->guiFactory()->addClient(this);
00408 }
00409 
00410 
00411 #include "kexipart.moc"
00412 
KDE Home | KDE Accessibility Home | Description of Access Keys