diff --git a/src/core/KexiMainWindowIface.h b/src/core/KexiMainWindowIface.h --- a/src/core/KexiMainWindowIface.h +++ b/src/core/KexiMainWindowIface.h @@ -275,6 +275,9 @@ One example is Project Navigator. */ virtual void addSearchableModel(KexiSearchableModel *model) = 0; + /*! Removes searchable model from the main window. @a model is not deleted. */ + virtual void removeSearchableModel(KexiSearchableModel *model) = 0; + virtual KexiUserFeedbackAgent* userFeedbackAgent() const = 0; //! Interface to the migrate manager diff --git a/src/core/KexiSearchableModel.h b/src/core/KexiSearchableModel.h --- a/src/core/KexiSearchableModel.h +++ b/src/core/KexiSearchableModel.h @@ -22,10 +22,29 @@ #include "kexicore_export.h" #include +#include class QModelIndex; class QVariant; class QString; +class KexiSearchableModel; + +//! Notifier used by KexiSearchableModel to inform about deleting of the model +class KEXICORE_EXPORT KexiSearchableModelDeleteNotifier : public QObject +{ + Q_OBJECT +public: + ~KexiSearchableModelDeleteNotifier(); + +Q_SIGNALS: + //! Emitted by KexiSearchableModel to inform about deleting of the model + void aboutToDelete(KexiSearchableModel *model); + +private: + KexiSearchableModelDeleteNotifier(); + + friend class KexiSearchableModel; +}; class KEXICORE_EXPORT KexiSearchableModel { @@ -38,6 +57,14 @@ virtual QString pathFromIndex(const QModelIndex &sourceIndex) const = 0; virtual bool highlightSearchableObject(const QModelIndex &index) = 0; virtual bool activateSearchableObject(const QModelIndex &index) = 0; + + //! Returns notifier object that can be used to connect to its notification signal. + //! This indirection is needed because the KexiSearchableModel class is not a QObject. + const KexiSearchableModelDeleteNotifier* deleteNotifier() const; + +private: + class Private; + const QScopedPointer d; }; #endif diff --git a/src/core/KexiSearchableModel.cpp b/src/core/KexiSearchableModel.cpp --- a/src/core/KexiSearchableModel.cpp +++ b/src/core/KexiSearchableModel.cpp @@ -19,10 +19,32 @@ #include "KexiSearchableModel.h" -KexiSearchableModel::KexiSearchableModel() +KexiSearchableModelDeleteNotifier::KexiSearchableModelDeleteNotifier() +{ +} + +KexiSearchableModelDeleteNotifier::~KexiSearchableModelDeleteNotifier() +{ +} + +class Q_DECL_HIDDEN KexiSearchableModel::Private +{ +public: + Private() {} + + KexiSearchableModelDeleteNotifier deleteNotifier; +}; + +KexiSearchableModel::KexiSearchableModel() : d(new Private) { } KexiSearchableModel::~KexiSearchableModel() { + emit d->deleteNotifier.aboutToDelete(this); +} + +const KexiSearchableModelDeleteNotifier* KexiSearchableModel::deleteNotifier() const +{ + return &d->deleteNotifier; } diff --git a/src/main/KexiMainWindow.h b/src/main/KexiMainWindow.h --- a/src/main/KexiMainWindow.h +++ b/src/main/KexiMainWindow.h @@ -289,7 +289,11 @@ /*! Add searchable model to the main window. This extends search to a new area. One example is Project Navigator. @see KexiMainWindowIface */ - virtual void addSearchableModel(KexiSearchableModel *model); + void addSearchableModel(KexiSearchableModel *model) override; + + /*! Removes searchable model from the main window. @a model is not deleted. + @see KexiMainWindowIface */ + void removeSearchableModel(KexiSearchableModel *model) override; //! Shows design tab when switching between objects or views. Depends on current window and view mode. void showDesignTabIfNeeded(int previousItemId); diff --git a/src/main/KexiMainWindow.cpp b/src/main/KexiMainWindow.cpp --- a/src/main/KexiMainWindow.cpp +++ b/src/main/KexiMainWindow.cpp @@ -4244,6 +4244,13 @@ } } +void KexiMainWindow::removeSearchableModel(KexiSearchableModel *model) +{ + if (d->tabbedToolBar) { + d->tabbedToolBar->removeSearchableModel(model); + } +} + void KexiMainWindow::setReasonableDialogSize(QDialog *dialog) { dialog->setMinimumSize(600, 400); diff --git a/src/main/KexiMainWindow_p.h b/src/main/KexiMainWindow_p.h --- a/src/main/KexiMainWindow_p.h +++ b/src/main/KexiMainWindow_p.h @@ -96,6 +96,8 @@ void addSearchableModel(KexiSearchableModel *model); + void removeSearchableModel(KexiSearchableModel *model); + KToolBar *createToolBar(const char *name, const QString& caption); void setCurrentTab(const QString& name); diff --git a/src/main/KexiMainWindow_p.cpp b/src/main/KexiMainWindow_p.cpp --- a/src/main/KexiMainWindow_p.cpp +++ b/src/main/KexiMainWindow_p.cpp @@ -1140,6 +1140,11 @@ d->searchLineEdit->addSearchableModel(model); } +void KexiTabbedToolBar::removeSearchableModel(KexiSearchableModel *model) +{ + d->searchLineEdit->removeSearchableModel(model); +} + KToolBar* KexiTabbedToolBar::createToolBar(const char* name, const QString& caption) { return d->createToolBar(name, caption); diff --git a/src/main/KexiSearchLineEdit.h b/src/main/KexiSearchLineEdit.h --- a/src/main/KexiSearchLineEdit.h +++ b/src/main/KexiSearchLineEdit.h @@ -47,6 +47,9 @@ One example is Project Navigator. */ void addSearchableModel(KexiSearchableModel *model); + /*! Removes searchable model from the main window. @a model is not deleted. */ + void removeSearchableModel(KexiSearchableModel *model); + /*! @return true if matching substrings are highlighted in completion list. @see setHighlightMatchingSubstrings() */ bool highlightMatchingSubstrings() const; diff --git a/src/main/KexiSearchLineEdit.cpp b/src/main/KexiSearchLineEdit.cpp --- a/src/main/KexiSearchLineEdit.cpp +++ b/src/main/KexiSearchLineEdit.cpp @@ -52,7 +52,14 @@ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + +public Q_SLOTS: + //! Adds a new model or updates information (model items) about existing one void addSearchableModel(KexiSearchableModel *model); + + //! Removes existing model + void removeSearchableModel(KexiSearchableModel *model); + private: class Private; Private * const d; @@ -68,10 +75,19 @@ ~Private() { qDeleteAll(searchableObjects); } - void updateCachedCount() { - if (searchableModels.isEmpty()) { + void removeSearchableModel(KexiSearchableModel *model) { + if (searchableModels.removeAll(model) == 0) { return; } + QMutableMapIterator it(searchableObjects); + while (it.hasNext()) { + it.next(); + if (it.value()->model == model) { + it.remove(); + } + } + } + void updateCachedCount() { cachedCount = 0; foreach (KexiSearchableModel* searchableModel, searchableModels) { cachedCount += searchableModel->searchableObjectCount(); @@ -146,9 +162,27 @@ void KexiSearchLineEditCompleterPopupModel::addSearchableModel(KexiSearchableModel *model) { - d->searchableModels.removeAll(model); + if (!model) { + return; + } + beginResetModel(); + d->removeSearchableModel(model); d->searchableModels.append(model); + connect(model->deleteNotifier(), &KexiSearchableModelDeleteNotifier::aboutToDelete, this, + &KexiSearchLineEditCompleterPopupModel::removeSearchableModel, Qt::UniqueConnection); d->updateCachedCount(); + endResetModel(); +} + +void KexiSearchLineEditCompleterPopupModel::removeSearchableModel(KexiSearchableModel *model) +{ + if (!model || !d->searchableModels.contains(model)) { + return; + } + beginResetModel(); + d->removeSearchableModel(model); + d->updateCachedCount(); + endResetModel(); } // ---- @@ -444,6 +478,11 @@ d->model->addSearchableModel(model); } +void KexiSearchLineEdit::removeSearchableModel(KexiSearchableModel *model) +{ + d->model->removeSearchableModel(model); +} + QPair KexiSearchLineEdit::mapCompletionIndexToSource(const QModelIndex &index) const { QModelIndex realIndex diff --git a/src/widget/navigator/KexiProjectNavigator.cpp b/src/widget/navigator/KexiProjectNavigator.cpp --- a/src/widget/navigator/KexiProjectNavigator.cpp +++ b/src/widget/navigator/KexiProjectNavigator.cpp @@ -255,7 +255,7 @@ QString* partManagerErrorMessages, bool addAsSearchableModel) { d->itemsPluginId = itemsPartClass; - + KexiMainWindowIface::global()->removeSearchableModel(d->model); // before model changes d->model->setProject(prj, itemsPartClass, partManagerErrorMessages); if (addAsSearchableModel) {