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 
00054     tristate askForOpeningInTextMode(KexiDialogBase *dlg, KexiPart::Item &item, 
00055         int supportedViewModes, int viewMode)
00056     {
00057         if (viewMode != Kexi::TextViewMode
00058             && supportedViewModes & Kexi::TextViewMode 
00059             && dlg->tempData()->proposeOpeningInTextViewModeBecauseOfProblems)
00060         {
00061             //ask
00062             KexiUtils::WaitCursorRemover remover;
00064             QString singleStatusString( dlg->singleStatusString() );
00065             if (!singleStatusString.isEmpty())
00066                 singleStatusString.prepend(QString("\n\n")+i18n("Details:")+" ");
00067             if (KMessageBox::No==KMessageBox::questionYesNo(0, 
00068                 ((viewMode == Kexi::DesignViewMode) 
00069                     ? i18n("Object \"%1\" could not be opened in Design View.").arg(item.name())
00070                     : i18n("Object could not be opened in Data View."))+"\n"
00071                 + i18n("Do you want to open it in Text View?") + singleStatusString, 0, 
00072                 KStdGuiItem::open(), KStdGuiItem::cancel()))
00073             {
00074     //          dlg->close(); //this will destroy dlg
00075                 return false;
00076             }
00077             return true;
00078         }
00079         return cancelled;
00080     }
00081 
00082     bool instanceActionsInitialized : 1;
00083 };
00084 }
00085 
00086 //----------------------------------------------------------------
00087 
00088 using namespace KexiPart;
00089 
00090 Part::Part(QObject *parent, const char *name, const QStringList &)
00091 : QObject(parent, name)
00092 , m_guiClient(0)
00093 , m_registeredPartID(-1) //no registered ID by default
00094 , d(new PartPrivate())
00095 {
00096     m_info = 0;
00097     m_supportedViewModes = Kexi::DataViewMode | Kexi::DesignViewMode;
00098     m_supportedUserViewModes = Kexi::DataViewMode;
00099     m_mainWin = 0;
00100     m_newObjectsAreDirty = false;
00101 }
00102 
00103 Part::Part(QObject* parent, StaticInfo *info)
00104 : QObject(parent, "StaticPart")
00105 , m_guiClient(0)
00106 , m_registeredPartID(-1) //no registered ID by default
00107 , d(new PartPrivate())
00108 {
00109     m_info = info;
00110     m_supportedViewModes = Kexi::DesignViewMode;
00111     m_supportedUserViewModes = 0;
00112     m_mainWin = 0;
00113     m_newObjectsAreDirty = false;
00114 }
00115 
00116 Part::~Part()
00117 {
00118     delete d;
00119 }
00120 
00121 void Part::createGUIClients(KexiMainWindow *win)
00122 {
00123     m_mainWin = win;
00124     if (!m_guiClient) {
00125         //create part's gui client
00126         m_guiClient = new GUIClient(m_mainWin, this, false, "part");
00127 
00128         //default actions for part's gui client:
00129         KAction *act = new KAction(m_names["instanceCaption"]+"...", info()->createItemIcon(), 0, this, 
00130             SLOT(slotCreate()), m_mainWin->actionCollection(), 
00131             KexiPart::nameForCreateAction(*info()));
00132         act->plug( m_mainWin->findPopupMenu("insert") );
00133 //      new KAction(m_names["instance"]+"...", info()->itemIcon(), 0, this, 
00134 //      SLOT(create()), m_guiClient->actionCollection(), (info()->objectName()+"part_create").latin1());
00135         //let init specific actions for parts
00136 //      initPartActions( m_guiClient->actionCollection() );
00137         m_mainWin->guiFactory()->addClient(m_guiClient); //this client is added permanently
00138 
00139         //create part instance's gui client
00140 //      m_instanceGuiClient = new GUIClient(win, this, true);
00141 
00142         //default actions for part instance's gui client:
00143         //NONE
00144         //let init specific actions for part instances
00145         for (int mode = 1; mode <= 0x01000; mode <<= 1) {
00146             if (m_supportedViewModes & mode) {
00147                 GUIClient *instanceGuiClient = new GUIClient(m_mainWin, 
00148                     this, true, Kexi::nameForViewMode(mode).latin1());
00149                 m_instanceGuiClients.insert(mode, instanceGuiClient);
00150 //              initInstanceActions( mode, instanceGuiClient->actionCollection() );
00151             }
00152         }
00153         // also add an instance common for all modes (mode==0)
00154         GUIClient *instanceGuiClient = new GUIClient(m_mainWin, this, true, "allViews");
00155         m_instanceGuiClients.insert(Kexi::AllViewModes, instanceGuiClient);
00156 //      initInstanceActions( Kexi::AllViewModes , instanceGuiClient->actionCollection() );
00157 
00158 //todo
00159         initPartActions();
00160 //      initActions();
00161     }
00162 }
00163 
00164 KActionCollection* Part::actionCollectionForMode(int viewMode) const
00165 {
00166     KXMLGUIClient *cli = m_instanceGuiClients[viewMode];
00167     return cli ? cli->actionCollection() : 0;
00168 }
00169 
00170 KAction* Part::createSharedAction(int mode, const QString &text, 
00171     const QString &pix_name, const KShortcut &cut, const char *name,
00172     const char *subclassName)
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 m_mainWin->createSharedAction(text, pix_name, cut, name, 
00180         instanceGuiClient->actionCollection(), subclassName);
00181 }
00182 
00183 KAction* Part::createSharedPartAction(const QString &text, 
00184     const QString &pix_name, const KShortcut &cut, const char *name,
00185     const char *subclassName)
00186 {
00187     if (!m_guiClient)
00188         return 0;
00189     return m_mainWin->createSharedAction(text, pix_name, cut, name, 
00190         m_guiClient->actionCollection(), subclassName);
00191 }
00192 
00193 KAction* Part::createSharedToggleAction(int mode, const QString &text, 
00194     const QString &pix_name, const KShortcut &cut, const char *name)
00195 {
00196     return createSharedAction(mode, text, pix_name, cut, name, "KToggleAction");
00197 }
00198 
00199 KAction* Part::createSharedPartToggleAction(const QString &text, 
00200     const QString &pix_name, const KShortcut &cut, const char *name)
00201 {
00202     return createSharedPartAction(text, pix_name, cut, name, "KToggleAction");
00203 }
00204 
00205 /*KAction* Part::sharedAction(int mode, const char* name, const char *classname)
00206 {
00207     GUIClient *instanceGuiClient = m_instanceGuiClients[mode];
00208     if (!instanceGuiClient) {
00209         kdDebug() << "KexiPart::createSharedAction(): no gui client for mode " << mode << "!" << endl;
00210         return 0;
00211     }
00212     return instanceGuiClient->actionCollection()->action(name, classname);
00213 }
00214 
00215 KAction* Part::sharedPartAction(int mode, const char* name, const char *classname)
00216 {
00217     if (!m_guiClient)
00218         return 0;
00219     return m_guiClient->actionCollection()->action(name, classname);
00220 }*/
00221 
00222 void Part::setActionAvailable(const char *action_name, bool avail)
00223 {
00224     QIntDictIterator<GUIClient> it( m_instanceGuiClients );
00225     for (;it.current();++it) {
00226         KAction *act = it.current()->actionCollection()->action(action_name);
00227         if (act) {
00228             act->setEnabled(avail);
00229             return;
00230         }
00231     }
00232 
00233     m_mainWin->setActionAvailable(action_name, avail);
00234 }
00235 
00236 KexiDialogBase* Part::openInstance(KexiMainWindow *win, KexiPart::Item &item, int viewMode,
00237     QMap<QString,QString>* staticObjectArgs)
00238 {
00239     //now it's the time for creating instance actions
00240     if (!d->instanceActionsInitialized) {
00241         initInstanceActions();
00242         d->instanceActionsInitialized = true;
00243     }
00244 
00245     m_status.clearStatus();
00246 //  KexiDialogBase *dlg = createInstance(win,item,viewMode);
00247 //  if (!dlg)
00248 //      return 0;
00249 //  QString capt = QString("%1 : %2").arg(item.name()).arg(instanceName());
00250     KexiDialogBase *dlg = new KexiDialogBase(win);
00251     dlg->m_supportedViewModes = m_supportedViewModes;
00252 //  dlg->m_neverSaved = item.neverSaved();
00253 //  dlg->m_currentViewMode = viewMode;
00254     dlg->m_part = this;
00255     dlg->m_item = &item;
00256     dlg->updateCaption();
00257 
00258     KexiDB::SchemaData sdata(m_info->projectPartID());
00259     sdata.setName( item.name() );
00260     sdata.setCaption( item.caption() );
00261     sdata.setDescription( item.description() );
00262 
00266 //  dlg->setCaption( capt );
00267 //  dlg->setTabCaption( item.name() );
00268     dlg->setId(item.identifier()); //not needed, but we did it
00269 //moved down    dlg->registerDialog();
00270     dlg->setIcon( SmallIcon( dlg->itemIcon() ) );
00271     if (dlg->mdiParent())
00272         dlg->mdiParent()->setIcon( *dlg->icon() );
00273 //  if (dlg->mainWidget())
00274 //      dlg->mainWidget()->setIcon( *dlg->icon() );
00275     dlg->stack()->setIcon( *dlg->icon() );
00276     dlg->m_tempData = createTempData(dlg);
00277 
00278     if (!item.neverSaved()) {
00279         //we have to load schema data for this dialog
00280         dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode);
00281         if (!dlg->m_schemaData) {
00282             //last chance:
00283             if (false == d->askForOpeningInTextMode(dlg, item, dlg->m_supportedViewModes, viewMode)) {
00284                 delete dlg;
00285                 return 0;
00286             }
00287             viewMode = Kexi::TextViewMode;
00288             dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode);
00289         }
00290         if (!dlg->m_schemaData) {
00291             if (!m_status.error())
00292                 m_status = Kexi::ObjectStatus( dlg->mainWin()->project()->dbConnection(), 
00293                     i18n("Could not load object's definition."), i18n("Object design may be corrupted."));
00294             m_status.append( 
00295                 Kexi::ObjectStatus(i18n("You can delete \"%1\" object and create it again.")
00296                 .arg(item.name()), QString::null) );
00297 
00298             dlg->close();
00299             delete dlg;
00300             return 0;
00301         }
00302     }
00303 
00304     bool switchingFailed = false;
00305     bool dummy;
00306     tristate res = dlg->switchToViewMode( viewMode, staticObjectArgs, dummy );
00307     if (!res) {
00308         tristate askForOpeningInTextModeRes
00309             = d->askForOpeningInTextMode(dlg, item, dlg->m_supportedViewModes, viewMode);
00310 //      if (viewMode==Kexi::DesignViewMode && dlg->isDesignModePreloadedForTextModeHackUsed(Kexi::TextViewMode))
00311 //          askForOpeningInTextModeRes = cancelled; //do not try
00312 //      else
00313         if (true == askForOpeningInTextModeRes) {
00314             delete dlg->m_schemaData; //old one
00315             dlg->close();
00316             delete dlg;
00317             //try in text mode
00318             return openInstance(win, item, Kexi::TextViewMode, staticObjectArgs);
00319         }
00320         else if (false == askForOpeningInTextModeRes) {
00321             delete dlg->m_schemaData; //old one
00322             dlg->close();
00323             delete dlg;
00324             return 0;
00325         }
00326         //dlg has an error info
00327         switchingFailed = true;
00328     }
00329     if (~res)
00330         switchingFailed = true;
00331 
00332     if (switchingFailed) {
00333         m_status = dlg->status();
00334         dlg->close();
00335         delete dlg;
00336         return 0;
00337     }
00338     dlg->registerDialog(); //ok?
00339     dlg->show();
00340 
00341     if (dlg->mdiParent() && dlg->mdiParent()->state()==KMdiChildFrm::Normal) //only resize dialog if it is in normal state
00342         dlg->resize(dlg->sizeHint());
00343 
00344     dlg->setMinimumSize(dlg->minimumSizeHint().width(),dlg->minimumSizeHint().height());
00345 
00346     //dirty only if it's a new object
00347     if (dlg->selectedView())
00348         dlg->selectedView()->setDirty( m_newObjectsAreDirty ? item.neverSaved() : false );
00349     
00350     return dlg;
00351 }
00352 
00353 void Part::slotCreate()
00354 {
00355     emit newObjectRequest( m_info );
00356 }
00357 
00358 KexiDB::SchemaData* Part::loadSchemaData(KexiDialogBase * /*dlg*/, const KexiDB::SchemaData& sdata, 
00359     int /*viewMode*/)
00360 {
00361     KexiDB::SchemaData *new_schema = new KexiDB::SchemaData();
00362     *new_schema = sdata;
00363     return new_schema;
00364 }
00365 
00366 bool Part::loadDataBlock( KexiDialogBase *dlg, QString &dataString, const QString& dataID)
00367 {
00368     if (!dlg->mainWin()->project()->dbConnection()->loadDataBlock( dlg->id(), dataString, dataID )) {
00369         m_status = Kexi::ObjectStatus( dlg->mainWin()->project()->dbConnection(), 
00370             i18n("Could not load object's data."), i18n("Data identifier: \"%1\".").arg(dataID) );
00371         m_status.append( *dlg );
00372         return false;
00373     }
00374     return true;
00375 }
00376 
00377 void Part::initPartActions()
00378 {
00379 }
00380 
00381 void Part::initInstanceActions()
00382 {
00383 }
00384 
00385 bool Part::remove(KexiMainWindow *win, KexiPart::Item &item)
00386 {
00387     if (!win || !win->project() || !win->project()->dbConnection())
00388         return false;
00389     KexiDB::Connection *conn = win->project()->dbConnection();
00390     return conn->removeObject( item.identifier() );
00391 }
00392 
00393 KexiDialogTempData* Part::createTempData(KexiDialogBase* dialog)
00394 {
00395     return new KexiDialogTempData(dialog);
00396 }
00397 
00398 QString Part::i18nMessage(const QCString& englishMessage, KexiDialogBase* dlg) const
00399 {
00400     Q_UNUSED(dlg);
00401     return QString(englishMessage).startsWith(":") ? QString::null : englishMessage;
00402 }
00403 
00404 void Part::setupCustomPropertyPanelTabs(KTabWidget *, KexiMainWindow*)
00405 {
00406 }
00407 
00408 QCString Part::instanceName() const
00409 {
00410     // "instanceName" should be already valid identifier but we're using
00411     // KexiUtils::string2Identifier() to be sure translators did it right.
00412     return KexiUtils::string2Identifier(m_names["instanceName"]).lower().latin1();
00413 }
00414 
00415 QString Part::instanceCaption() const
00416 {
00417     return m_names["instanceCaption"];
00418 }
00419 
00420 tristate Part::rename(KexiMainWindow *win, KexiPart::Item &item, const QString& newName)
00421 {
00422     Q_UNUSED(win);
00423     Q_UNUSED(item);
00424     Q_UNUSED(newName);
00425     return true;
00426 }
00427 
00428 //-------------------------------------------------------------------------
00429 
00430 
00431 GUIClient::GUIClient(KexiMainWindow *win, Part* part, bool partInstanceClient, const char* nameSuffix)
00432  : QObject(part, 
00433    (part->info()->objectName() 
00434     + (nameSuffix ? QString(":%1").arg(nameSuffix) : QString())).latin1() )
00435  , KXMLGUIClient(win)
00436 {
00437     if(!win->project()->data()->userMode())
00438         setXMLFile(QString::fromLatin1("kexi")+part->info()->objectName()
00439             +"part"+(partInstanceClient?"inst":"")+"ui.rc");
00440 
00441 //  new KAction(part->m_names["new"], part->info()->itemIcon(), 0, this, 
00442 //      SLOT(create()), actionCollection(), (part->info()->objectName()+"part_create").latin1());
00443 
00444 //  new KAction(i18nInstanceName+"...", part->info()->itemIcon(), 0, this, 
00445 //      SLOT(create()), actionCollection(), (part->info()->objectName()+"part_create").latin1());
00446 
00447 //  win->guiFactory()->addClient(this);
00448 }
00449 
00450 
00451 #include "kexipart.moc"
00452 
KDE Home | KDE Accessibility Home | Description of Access Keys