00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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)
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)
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
00126 m_guiClient = new GUIClient(m_mainWin, this, false, "part");
00127
00128
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
00134
00135
00136
00137 m_mainWin->guiFactory()->addClient(m_guiClient);
00138
00139
00140
00141
00142
00143
00144
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
00151 }
00152 }
00153
00154 GUIClient *instanceGuiClient = new GUIClient(m_mainWin, this, true, "allViews");
00155 m_instanceGuiClients.insert(Kexi::AllViewModes, instanceGuiClient);
00156
00157
00158
00159 initPartActions();
00160
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
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
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
00240 if (!d->instanceActionsInitialized) {
00241 initInstanceActions();
00242 d->instanceActionsInitialized = true;
00243 }
00244
00245 m_status.clearStatus();
00246
00247
00248
00249
00250 KexiDialogBase *dlg = new KexiDialogBase(win);
00251 dlg->m_supportedViewModes = m_supportedViewModes;
00252
00253
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
00267
00268 dlg->setId(item.identifier());
00269
00270 dlg->setIcon( SmallIcon( dlg->itemIcon() ) );
00271 if (dlg->mdiParent())
00272 dlg->mdiParent()->setIcon( *dlg->icon() );
00273
00274
00275 dlg->stack()->setIcon( *dlg->icon() );
00276 dlg->m_tempData = createTempData(dlg);
00277
00278 if (!item.neverSaved()) {
00279
00280 dlg->m_schemaData = loadSchemaData(dlg, sdata, viewMode);
00281 if (!dlg->m_schemaData) {
00282
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
00311
00312
00313 if (true == askForOpeningInTextModeRes) {
00314 delete dlg->m_schemaData;
00315 dlg->close();
00316 delete dlg;
00317
00318 return openInstance(win, item, Kexi::TextViewMode, staticObjectArgs);
00319 }
00320 else if (false == askForOpeningInTextModeRes) {
00321 delete dlg->m_schemaData;
00322 dlg->close();
00323 delete dlg;
00324 return 0;
00325 }
00326
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();
00339 dlg->show();
00340
00341 if (dlg->mdiParent() && dlg->mdiParent()->state()==KMdiChildFrm::Normal)
00342 dlg->resize(dlg->sizeHint());
00343
00344 dlg->setMinimumSize(dlg->minimumSizeHint().width(),dlg->minimumSizeHint().height());
00345
00346
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 * , const KexiDB::SchemaData& sdata,
00359 int )
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
00411
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
00442
00443
00444
00445
00446
00447
00448 }
00449
00450
00451 #include "kexipart.moc"
00452