QtHelpDocumentationDialog: moved the QtHelpFiltersDialog functionality into this one.

Fri, 13 Sep 2019 18:54:34 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 13 Sep 2019 18:54:34 +0200
changeset 7231
0dcb92a9687d
parent 7230
2ee6af6381c8
child 7232
0b840f7ed593

QtHelpDocumentationDialog: moved the QtHelpFiltersDialog functionality into this one.

eric6.e4p file | annotate | diff | comparison | revisions
eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.py file | annotate | diff | comparison | revisions
eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.ui file | annotate | diff | comparison | revisions
eric6/WebBrowser/QtHelp/QtHelpFiltersDialog.py file | annotate | diff | comparison | revisions
eric6/WebBrowser/QtHelp/QtHelpFiltersDialog.ui file | annotate | diff | comparison | revisions
eric6/WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
--- a/eric6.e4p	Tue Sep 10 19:36:17 2019 +0200
+++ b/eric6.e4p	Fri Sep 13 18:54:34 2019 +0200
@@ -1384,7 +1384,6 @@
     <Source>eric6/WebBrowser/QtHelp/HelpTopicDialog.py</Source>
     <Source>eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.py</Source>
     <Source>eric6/WebBrowser/QtHelp/QtHelpDocumentationSelectionDialog.py</Source>
-    <Source>eric6/WebBrowser/QtHelp/QtHelpFiltersDialog.py</Source>
     <Source>eric6/WebBrowser/QtHelp/__init__.py</Source>
     <Source>eric6/WebBrowser/SafeBrowsing/SafeBrowsingAPIClient.py</Source>
     <Source>eric6/WebBrowser/SafeBrowsing/SafeBrowsingCache.py</Source>
@@ -1958,7 +1957,6 @@
     <Form>eric6/WebBrowser/QtHelp/HelpTopicDialog.ui</Form>
     <Form>eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.ui</Form>
     <Form>eric6/WebBrowser/QtHelp/QtHelpDocumentationSelectionDialog.ui</Form>
-    <Form>eric6/WebBrowser/QtHelp/QtHelpFiltersDialog.ui</Form>
     <Form>eric6/WebBrowser/SafeBrowsing/SafeBrowsingDialog.ui</Form>
     <Form>eric6/WebBrowser/SearchWidget.ui</Form>
     <Form>eric6/WebBrowser/Session/SessionManagerDialog.ui</Form>
--- a/eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.py	Tue Sep 10 19:36:17 2019 +0200
+++ b/eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.py	Fri Sep 13 18:54:34 2019 +0200
@@ -7,9 +7,11 @@
 Module implementing a dialog to manage the QtHelp documentation database.
 """
 
+import sqlite3
 
 from PyQt5.QtCore import pyqtSlot, Qt, QItemSelectionModel
-from PyQt5.QtWidgets import QDialog
+from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QListWidgetItem, \
+    QInputDialog, QLineEdit
 from PyQt5.QtHelp import QHelpEngineCore
 
 from E5Gui import E5MessageBox, E5FileDialog
@@ -32,18 +34,51 @@
         super(QtHelpDocumentationDialog, self).__init__(parent)
         self.setupUi(self)
         
-        self.removeButton.setEnabled(False)
-        
         self.__engine = engine
         self.__mw = parent
         
+        self.__initDocumentsTab()
+        self.__initFiltersTab()
+        
+        self.tabWidget.setCurrentIndex(0)
+    
+    @pyqtSlot(int)
+    def on_tabWidget_currentChanged(self, index):
+        """
+        Private slot handling a change of the current tab.
+        
+        @param index index of the current tab
+        @type int
+        """
+        if index != 1 and \
+           (self.__hasChangedFilters() or self.__removedAttributes):
+            yes = E5MessageBox.yesNo(
+                self,
+                self.tr("Unsaved Filter Changes"),
+                self.tr("""The page contains unsaved changes. Shall they be"""
+                        """ saved?"""),
+                yesDefault=True)
+            if yes:
+                self.on_applyFilterChangesButton_clicked()
+    
+    ##################################################################
+    ## Documentations Tab
+    ##################################################################
+    
+    def __initDocumentsTab(self):
+        """
+        Private method to initialize the documents tab.
+        """
+        self.documentsList.clear()
+        self.removeDocumentsButton.setEnabled(False)
+        
         docs = self.__engine.registeredDocumentations()
         self.documentsList.addItems(docs)
-        
+
         self.__registeredDocs = []
         self.__unregisteredDocs = []
         self.__tabsToClose = []
-        
+
         try:
             self.__pluginHelpDocuments = \
                 e5App().getObject("PluginManager").getPluginQtHelpFiles()
@@ -60,11 +95,11 @@
         """
         Private slot handling a change of the documents selection.
         """
-        self.removeButton.setEnabled(
+        self.removeDocumentsButton.setEnabled(
             len(self.documentsList.selectedItems()) != 0)
     
     @pyqtSlot()
-    def on_addButton_clicked(self):
+    def on_addDocumentsButton_clicked(self):
         """
         Private slot to add QtHelp documents to the help database.
         """
@@ -144,9 +179,11 @@
             self.__registeredDocs.append(ns)
             if ns in self.__unregisteredDocs:
                 self.__unregisteredDocs.remove(ns)
+        
+        self.__initFiltersTab()
 
     @pyqtSlot()
-    def on_removeButton_clicked(self):
+    def on_removeDocumentsButton_clicked(self):
         """
         Private slot to remove a document from the help database.
         """
@@ -189,11 +226,13 @@
             self.documentsList.setCurrentRow(
                 0, QItemSelectionModel.ClearAndSelect)
     
-    def hasChanges(self):
+    def hasDocumentationChanges(self):
         """
-        Public slot to test the dialog for changes.
+        Public slot to test the dialog for changes of configured QtHelp
+        documents.
         
         @return flag indicating presence of changes
+        @rtype bool
         """
         return len(self.__registeredDocs) > 0 or \
             len(self.__unregisteredDocs) > 0
@@ -202,6 +241,293 @@
         """
         Public method to get the list of tabs to close.
         
-        @return list of tab ids to be closed (list of integers)
+        @return list of tab ids to be closed
+        @rtype list of int
         """
         return self.__tabsToClose
+    
+    ##################################################################
+    ## Filters Tab
+    ##################################################################
+    
+    def __initFiltersTab(self):
+        """
+        Private method to initialize the filters tab.
+        """
+        self.removeFiltersButton.setEnabled(False)
+        self.removeAttributesButton.setEnabled(False)
+        
+        # save the current and selected filters
+        currentFilter = self.filtersList.currentItem()
+        if currentFilter:
+            currentFilterText = currentFilter.text()
+        else:
+            currentFilterText = ""
+        selectedFiltersText = [
+            itm.text() for itm in self.filtersList.selectedItems()]
+        
+        # save the selected attributes
+        selectedAttributesText = [
+            itm.text(0) for itm in self.attributesList.selectedItems()]
+        
+        self.filtersList.clear()
+        self.attributesList.clear()
+        
+        helpEngineCore = QHelpEngineCore(self.__engine.collectionFile())
+        
+        self.__removedFilters = []
+        self.__filterMap = {}
+        self.__filterMapBackup = {}
+        self.__removedAttributes = []
+        
+        for customFilter in helpEngineCore.customFilters():
+            atts = helpEngineCore.filterAttributes(customFilter)
+            self.__filterMapBackup[customFilter] = atts
+            if customFilter not in self.__filterMap:
+                self.__filterMap[customFilter] = atts
+        
+        self.filtersList.addItems(sorted(self.__filterMap.keys()))
+        for attr in helpEngineCore.filterAttributes():
+            QTreeWidgetItem(self.attributesList, [attr])
+        self.attributesList.sortItems(0, Qt.AscendingOrder)
+        
+        if selectedFiltersText or currentFilterText or selectedAttributesText:
+            # restore the selected filters
+            for txt in selectedFiltersText:
+                items = self.filtersList.findItems(txt, Qt.MatchExactly)
+                for itm in items:
+                    itm.setSelected(True)
+            # restore the current filter
+            if currentFilterText:
+                items = self.filtersList.findItems(currentFilterText,
+                                                   Qt.MatchExactly)
+                if items:
+                    self.filtersList.setCurrentItem(
+                        items[0], QItemSelectionModel.NoUpdate)
+            # restore the selected attributes
+            for txt in selectedAttributesText:
+                items = self.attributesList.findItems(txt, Qt.MatchExactly, 0)
+                for itm in items:
+                    itm.setSelected(True)
+        elif self.__filterMap:
+            self.filtersList.setCurrentRow(0)
+    
+    @pyqtSlot(QListWidgetItem, QListWidgetItem)
+    def on_filtersList_currentItemChanged(self, current, previous):
+        """
+        Private slot to update the attributes depending on the current filter.
+        
+        @param current reference to the current item (QListWidgetitem)
+        @param previous reference to the previous current item
+            (QListWidgetItem)
+        """
+        checkedList = []
+        if current is not None:
+            checkedList = self.__filterMap[current.text()]
+        for index in range(0, self.attributesList.topLevelItemCount()):
+            itm = self.attributesList.topLevelItem(index)
+            if itm.text(0) in checkedList:
+                itm.setCheckState(0, Qt.Checked)
+            else:
+                itm.setCheckState(0, Qt.Unchecked)
+    
+    @pyqtSlot()
+    def on_filtersList_itemSelectionChanged(self):
+        """
+        Private slot handling a change of selected filters.
+        """
+        self.removeFiltersButton.setEnabled(
+            len(self.filtersList.selectedItems()) > 0)
+    
+    @pyqtSlot(QTreeWidgetItem, int)
+    def on_attributesList_itemChanged(self, item, column):
+        """
+        Private slot to handle a change of an attribute.
+        
+        @param item reference to the changed item (QTreeWidgetItem)
+        @param column column containing the change (integer)
+        """
+        if self.filtersList.currentItem() is None:
+            return
+        
+        customFilter = self.filtersList.currentItem().text()
+        if customFilter not in self.__filterMap:
+            return
+        
+        newAtts = []
+        for index in range(0, self.attributesList.topLevelItemCount()):
+            itm = self.attributesList.topLevelItem(index)
+            if itm.checkState(0) == Qt.Checked:
+                newAtts.append(itm.text(0))
+        self.__filterMap[customFilter] = newAtts
+    
+    @pyqtSlot()
+    def on_attributesList_itemSelectionChanged(self):
+        """
+        Private slot handling the selection of attributes.
+        """
+        self.removeAttributesButton.setEnabled(
+            len(self.attributesList.selectedItems()) != 0)
+    
+    @pyqtSlot()
+    def on_addFilterButton_clicked(self):
+        """
+        Private slot to add a new filter.
+        """
+        customFilter, ok = QInputDialog.getText(
+            None,
+            self.tr("Add Filter"),
+            self.tr("Filter name:"),
+            QLineEdit.Normal)
+        if not customFilter:
+            return
+        
+        if customFilter not in self.__filterMap:
+            self.__filterMap[customFilter] = []
+            self.filtersList.addItem(customFilter)
+        
+        itm = self.filtersList.findItems(
+            customFilter, Qt.MatchCaseSensitive)[0]
+        self.filtersList.setCurrentItem(itm)
+    
+    @pyqtSlot()
+    def on_removeFiltersButton_clicked(self):
+        """
+        Private slot to remove the selected filters.
+        """
+        ok = E5MessageBox.yesNo(
+            self,
+            self.tr("Remove Filters"),
+            self.tr(
+                """Do you really want to remove the selected filters """
+                """from the database?"""))
+        if not ok:
+            return
+        
+        items = self.filtersList.selectedItems()
+        for item in items:
+            itm = self.filtersList.takeItem(self.filtersList.row(item))
+            if itm is None:
+                continue
+            
+            del self.__filterMap[itm.text()]
+            self.__removedFilters.append(itm.text())
+            del itm
+        
+        if self.filtersList.count():
+            self.filtersList.setCurrentRow(
+                0, QItemSelectionModel.ClearAndSelect)
+    
+    @pyqtSlot()
+    def on_removeAttributesButton_clicked(self):
+        """
+        Private slot to remove the selected filter attributes.
+        """
+        ok = E5MessageBox.yesNo(
+            self,
+            self.tr("Remove Attributes"),
+            self.tr(
+                """Do you really want to remove the selected attributes """
+                """from the database?"""))
+        if not ok:
+            return
+        
+        items = self.attributesList.selectedItems()
+        for item in items:
+            itm = self.attributesList.takeTopLevelItem(
+                self.attributesList.indexOfTopLevelItem(item))
+            if itm is None:
+                continue
+            
+            attr = itm.text(0)
+            self.__removedAttributes.append(attr)
+            for customFilter in self.__filterMap:
+                if attr in self.__filterMap[customFilter]:
+                    self.__filterMap[customFilter].remove(attr)
+            
+            del itm
+    
+    @pyqtSlot()
+    def on_unusedAttributesButton_clicked(self):
+        """
+        Private slot to select all unused attributes.
+        """
+        # step 1: determine all used attributes
+        attributes = set()
+        for customFilter in self.__filterMap:
+            attributes |= set(self.__filterMap[customFilter])
+        
+        # step 2: select all unused attribute items
+        self.attributesList.clearSelection()
+        for row in range(self.attributesList.topLevelItemCount()):
+            itm = self.attributesList.topLevelItem(row)
+            if itm.text(0) not in attributes:
+                itm.setSelected(True)
+    
+    def __removeAttributes(self):
+        """
+        Private method to remove attributes from the Qt Help database.
+        """
+        try:
+            self.__db = sqlite3.connect(self.__engine.collectionFile())
+        except sqlite3.DatabaseError:
+            pass        # ignore database errors
+        
+        for attr in self.__removedAttributes:
+            self.__db.execute(
+                "DELETE FROM FilterAttributeTable WHERE Name = '{0}'"
+                .format(attr))
+        self.__db.commit()
+        self.__db.close()
+    
+    @pyqtSlot()
+    def on_applyFilterChangesButton_clicked(self):
+        """
+        Private slot to apply the filter changes.
+        """
+        if self.__hasChangedFilters():
+            for customFilter in self.__removedFilters:
+                self.__engine.removeCustomFilter(customFilter)
+            for customFilter in self.__filterMap:
+                self.__engine.addCustomFilter(
+                    customFilter, self.__filterMap[customFilter])
+        
+        if self.__removedAttributes:
+            self.__removeAttributes()
+
+    def __hasChangedFilters(self):
+        """
+        Private method to determine, if there are filter changes.
+        
+        @return flag indicating the presence of filter changes
+        @rtype bool
+        """
+        filtersChanged = False
+        if len(self.__filterMapBackup) != len(self.__filterMap):
+            filtersChanged = True
+        else:
+            for customFilter in self.__filterMapBackup:
+                if customFilter not in self.__filterMap:
+                    filtersChanged = True
+                else:
+                    oldFilterAtts = self.__filterMapBackup[customFilter]
+                    newFilterAtts = self.__filterMap[customFilter]
+                    if len(oldFilterAtts) != len(newFilterAtts):
+                        filtersChanged = True
+                    else:
+                        for attr in oldFilterAtts:
+                            if attr not in newFilterAtts:
+                                filtersChanged = True
+                                break
+
+                if filtersChanged:
+                    break
+        
+        return filtersChanged
+    
+    @pyqtSlot()
+    def on_resetFilterChangesButton_clicked(self):
+        """
+        Private slot to forget the filter changes and reset the tab.
+        """
+        self.__initFiltersTab()
--- a/eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.ui	Tue Sep 10 19:36:17 2019 +0200
+++ b/eric6/WebBrowser/QtHelp/QtHelpDocumentationDialog.ui	Fri Sep 13 18:54:34 2019 +0200
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>500</width>
-    <height>450</height>
+    <width>600</width>
+    <height>500</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -16,93 +16,270 @@
   <property name="sizeGripEnabled">
    <bool>true</bool>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QLabel" name="label">
-     <property name="text">
-      <string>Registered Documents</string>
-     </property>
-    </widget>
-   </item>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
-    <layout class="QGridLayout" name="gridLayout">
-     <item row="0" column="0" rowspan="6">
-      <widget class="QListWidget" name="documentsList">
-       <property name="alternatingRowColors">
-        <bool>true</bool>
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
+      <number>1</number>
+     </property>
+     <widget class="QWidget" name="documentsTab">
+      <attribute name="title">
+       <string>Registered Documents</string>
+      </attribute>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <property name="leftMargin">
+        <number>3</number>
        </property>
-       <property name="selectionMode">
-        <enum>QAbstractItemView::ExtendedSelection</enum>
+       <property name="topMargin">
+        <number>3</number>
+       </property>
+       <property name="rightMargin">
+        <number>3</number>
+       </property>
+       <property name="bottomMargin">
+        <number>3</number>
        </property>
-       <property name="sortingEnabled">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="1">
-      <widget class="QPushButton" name="addButton">
-       <property name="toolTip">
-        <string>Press to select QtHelp documents to add to the database</string>
+       <item>
+        <widget class="QListWidget" name="documentsList">
+         <property name="alternatingRowColors">
+          <bool>true</bool>
+         </property>
+         <property name="selectionMode">
+          <enum>QAbstractItemView::ExtendedSelection</enum>
+         </property>
+         <property name="sortingEnabled">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <item>
+          <widget class="QPushButton" name="addDocumentsButton">
+           <property name="toolTip">
+            <string>Press to select QtHelp documents to add to the database</string>
+           </property>
+           <property name="text">
+            <string>Add...</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="addPluginButton">
+           <property name="toolTip">
+            <string>Press to select QtHelp documents provided by a plug-in to add to the database</string>
+           </property>
+           <property name="text">
+            <string>Add from Plug-ins...</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="removeDocumentsButton">
+           <property name="toolTip">
+            <string>Press to remove the selected documents from the database</string>
+           </property>
+           <property name="text">
+            <string>Remove</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="Line" name="line">
+           <property name="lineWidth">
+            <number>2</number>
+           </property>
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="managePluginButton">
+           <property name="toolTip">
+            <string>Select to manage the plug-in provided documentation sets</string>
+           </property>
+           <property name="text">
+            <string>Manage Plug-ins...</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="verticalSpacer">
+           <property name="orientation">
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>20</width>
+             <height>17</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="filtersTab">
+      <attribute name="title">
+       <string>Filters</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <property name="leftMargin">
+        <number>3</number>
        </property>
-       <property name="text">
-        <string>Add...</string>
+       <property name="topMargin">
+        <number>3</number>
        </property>
-      </widget>
-     </item>
-     <item row="1" column="1">
-      <widget class="QPushButton" name="addPluginButton">
-       <property name="toolTip">
-        <string>Press to select QtHelp documents provided by a plug-in to add to the database</string>
+       <property name="rightMargin">
+        <number>3</number>
        </property>
-       <property name="text">
-        <string>Add from Plug-ins...</string>
+       <property name="bottomMargin">
+        <number>3</number>
        </property>
-      </widget>
-     </item>
-     <item row="2" column="1">
-      <widget class="QPushButton" name="removeButton">
-       <property name="toolTip">
-        <string>Press to remove the selected documents from the database</string>
-       </property>
-       <property name="text">
-        <string>Remove</string>
-       </property>
-      </widget>
-     </item>
-     <item row="3" column="1">
-      <widget class="Line" name="line">
-       <property name="lineWidth">
-        <number>2</number>
-       </property>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-      </widget>
-     </item>
-     <item row="4" column="1">
-      <widget class="QPushButton" name="managePluginButton">
-       <property name="toolTip">
-        <string>Select to manage the plug-in provided documentation sets</string>
-       </property>
-       <property name="text">
-        <string>Manage Plug-ins...</string>
-       </property>
-      </widget>
-     </item>
-     <item row="5" column="1">
-      <spacer name="verticalSpacer">
-       <property name="orientation">
-        <enum>Qt::Vertical</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>20</width>
-         <height>17</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-    </layout>
+       <item>
+        <layout class="QGridLayout" name="gridLayout">
+         <item row="0" column="0" colspan="2">
+          <widget class="QLabel" name="label">
+           <property name="text">
+            <string>Filters:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="2" colspan="2">
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Attributes:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0" colspan="2">
+          <widget class="QListWidget" name="filtersList">
+           <property name="alternatingRowColors">
+            <bool>true</bool>
+           </property>
+           <property name="selectionMode">
+            <enum>QAbstractItemView::ExtendedSelection</enum>
+           </property>
+           <property name="sortingEnabled">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="2" colspan="2">
+          <widget class="QTreeWidget" name="attributesList">
+           <property name="alternatingRowColors">
+            <bool>true</bool>
+           </property>
+           <property name="selectionMode">
+            <enum>QAbstractItemView::ExtendedSelection</enum>
+           </property>
+           <property name="rootIsDecorated">
+            <bool>false</bool>
+           </property>
+           <property name="sortingEnabled">
+            <bool>true</bool>
+           </property>
+           <property name="headerHidden">
+            <bool>true</bool>
+           </property>
+           <column>
+            <property name="text">
+             <string notr="true">1</string>
+            </property>
+           </column>
+          </widget>
+         </item>
+         <item row="2" column="0">
+          <widget class="QPushButton" name="addFilterButton">
+           <property name="toolTip">
+            <string>Press to add a new filter</string>
+           </property>
+           <property name="text">
+            <string>Add Filter ...</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QPushButton" name="removeFiltersButton">
+           <property name="toolTip">
+            <string>Press to remove the selected filters</string>
+           </property>
+           <property name="text">
+            <string>Remove Filters</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="2">
+          <widget class="QPushButton" name="removeAttributesButton">
+           <property name="toolTip">
+            <string>Press to remove the selected attributes</string>
+           </property>
+           <property name="text">
+            <string>Remove Attributes</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="3">
+          <widget class="QPushButton" name="unusedAttributesButton">
+           <property name="statusTip">
+            <string>Press to select all unused attributes</string>
+           </property>
+           <property name="text">
+            <string>Select Unused</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="Line" name="line_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <spacer name="horizontalSpacer">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="applyFilterChangesButton">
+           <property name="toolTip">
+            <string>Press to apply the filter and attribute changes</string>
+           </property>
+           <property name="text">
+            <string>Apply</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="resetFilterChangesButton">
+           <property name="toolTip">
+            <string>Press to reset the filter and attribute changes</string>
+           </property>
+           <property name="text">
+            <string>Reset</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </widget>
    </item>
    <item>
     <widget class="QDialogButtonBox" name="buttonBox">
@@ -117,10 +294,20 @@
   </layout>
  </widget>
  <tabstops>
+  <tabstop>tabWidget</tabstop>
   <tabstop>documentsList</tabstop>
-  <tabstop>addButton</tabstop>
+  <tabstop>addDocumentsButton</tabstop>
   <tabstop>addPluginButton</tabstop>
-  <tabstop>removeButton</tabstop>
+  <tabstop>removeDocumentsButton</tabstop>
+  <tabstop>managePluginButton</tabstop>
+  <tabstop>filtersList</tabstop>
+  <tabstop>addFilterButton</tabstop>
+  <tabstop>removeFiltersButton</tabstop>
+  <tabstop>attributesList</tabstop>
+  <tabstop>removeAttributesButton</tabstop>
+  <tabstop>unusedAttributesButton</tabstop>
+  <tabstop>applyFilterChangesButton</tabstop>
+  <tabstop>resetFilterChangesButton</tabstop>
  </tabstops>
  <resources/>
  <connections>
--- a/eric6/WebBrowser/QtHelp/QtHelpFiltersDialog.py	Tue Sep 10 19:36:17 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing a dialog to manage the QtHelp filters.
-"""
-
-
-import sqlite3
-
-from PyQt5.QtCore import pyqtSlot, Qt, QItemSelectionModel
-from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QListWidgetItem, \
-    QInputDialog, QLineEdit
-from PyQt5.QtHelp import QHelpEngineCore
-
-from E5Gui import E5MessageBox
-
-from .Ui_QtHelpFiltersDialog import Ui_QtHelpFiltersDialog
-
-
-class QtHelpFiltersDialog(QDialog, Ui_QtHelpFiltersDialog):
-    """
-    Class implementing a dialog to manage the QtHelp filters.
-    """
-    def __init__(self, engine, parent=None):
-        """
-        Constructor
-        
-        @param engine reference to the help engine (QHelpEngine)
-        @param parent reference to the parent widget (QWidget)
-        """
-        super(QtHelpFiltersDialog, self).__init__(parent)
-        self.setupUi(self)
-        
-        self.removeButton.setEnabled(False)
-        self.removeAttributeButton.setEnabled(False)
-        
-        self.__engine = engine
-        
-        self.filtersList.clear()
-        self.attributesList.clear()
-        
-        helpEngineCore = QHelpEngineCore(self.__engine.collectionFile())
-        
-        self.__removedFilters = []
-        self.__filterMap = {}
-        self.__filterMapBackup = {}
-        self.__removedAttributes = []
-        
-        for customFilter in helpEngineCore.customFilters():
-            atts = helpEngineCore.filterAttributes(customFilter)
-            self.__filterMapBackup[customFilter] = atts
-            if customFilter not in self.__filterMap:
-                self.__filterMap[customFilter] = atts
-        
-        self.filtersList.addItems(sorted(self.__filterMap.keys()))
-        for attr in helpEngineCore.filterAttributes():
-            QTreeWidgetItem(self.attributesList, [attr])
-        self.attributesList.sortItems(0, Qt.AscendingOrder)
-        
-        if self.__filterMap:
-            self.filtersList.setCurrentRow(0)
-    
-    @pyqtSlot(QListWidgetItem, QListWidgetItem)
-    def on_filtersList_currentItemChanged(self, current, previous):
-        """
-        Private slot to update the attributes depending on the current filter.
-        
-        @param current reference to the current item (QListWidgetitem)
-        @param previous reference to the previous current item
-            (QListWidgetItem)
-        """
-        checkedList = []
-        if current is not None:
-            checkedList = self.__filterMap[current.text()]
-        for index in range(0, self.attributesList.topLevelItemCount()):
-            itm = self.attributesList.topLevelItem(index)
-            if itm.text(0) in checkedList:
-                itm.setCheckState(0, Qt.Checked)
-            else:
-                itm.setCheckState(0, Qt.Unchecked)
-    
-    @pyqtSlot()
-    def on_filtersList_itemSelectionChanged(self):
-        """
-        Private slot handling a change of selected filters.
-        """
-        self.removeButton.setEnabled(
-            len(self.filtersList.selectedItems()) > 0)
-    
-    @pyqtSlot(QTreeWidgetItem, int)
-    def on_attributesList_itemChanged(self, item, column):
-        """
-        Private slot to handle a change of an attribute.
-        
-        @param item reference to the changed item (QTreeWidgetItem)
-        @param column column containing the change (integer)
-        """
-        if self.filtersList.currentItem() is None:
-            return
-        
-        customFilter = self.filtersList.currentItem().text()
-        if customFilter not in self.__filterMap:
-            return
-        
-        newAtts = []
-        for index in range(0, self.attributesList.topLevelItemCount()):
-            itm = self.attributesList.topLevelItem(index)
-            if itm.checkState(0) == Qt.Checked:
-                newAtts.append(itm.text(0))
-        self.__filterMap[customFilter] = newAtts
-    
-    @pyqtSlot()
-    def on_attributesList_itemSelectionChanged(self):
-        """
-        Private slot handling the selection of attributes.
-        """
-        self.removeAttributeButton.setEnabled(
-            len(self.attributesList.selectedItems()) != 0)
-    
-    @pyqtSlot()
-    def on_addButton_clicked(self):
-        """
-        Private slot to add a new filter.
-        """
-        customFilter, ok = QInputDialog.getText(
-            None,
-            self.tr("Add Filter"),
-            self.tr("Filter name:"),
-            QLineEdit.Normal)
-        if not customFilter:
-            return
-        
-        if customFilter not in self.__filterMap:
-            self.__filterMap[customFilter] = []
-            self.filtersList.addItem(customFilter)
-        
-        itm = self.filtersList.findItems(
-            customFilter, Qt.MatchCaseSensitive)[0]
-        self.filtersList.setCurrentItem(itm)
-    
-    @pyqtSlot()
-    def on_removeButton_clicked(self):
-        """
-        Private slot to remove the selected filters.
-        """
-        ok = E5MessageBox.yesNo(
-            self,
-            self.tr("Remove Filters"),
-            self.tr(
-                """Do you really want to remove the selected filters """
-                """from the database?"""))
-        if not ok:
-            return
-        
-        items = self.filtersList.selectedItems()
-        for item in items:
-            itm = self.filtersList.takeItem(self.filtersList.row(item))
-            if itm is None:
-                continue
-            
-            del self.__filterMap[itm.text()]
-            self.__removedFilters.append(itm.text())
-            del itm
-        
-        if self.filtersList.count():
-            self.filtersList.setCurrentRow(
-                0, QItemSelectionModel.ClearAndSelect)
-    
-    @pyqtSlot()
-    def on_removeAttributeButton_clicked(self):
-        """
-        Private slot to remove the selected filter attributes.
-        """
-        ok = E5MessageBox.yesNo(
-            self,
-            self.tr("Remove Attributes"),
-            self.tr(
-                """Do you really want to remove the selected attributes """
-                """from the database?"""))
-        if not ok:
-            return
-        
-        items = self.attributesList.selectedItems()
-        for item in items:
-            itm = self.attributesList.takeTopLevelItem(
-                self.attributesList.indexOfTopLevelItem(item))
-            if itm is None:
-                continue
-            
-            attr = itm.text(0)
-            self.__removedAttributes.append(attr)
-            for customFilter in self.__filterMap:
-                if attr in self.__filterMap[customFilter]:
-                    self.__filterMap[customFilter].remove(attr)
-            
-            del itm
-    
-    @pyqtSlot()
-    def on_unusedAttributesButton_clicked(self):
-        """
-        Private slot to select all unused attributes.
-        """
-        # step 1: determine all used attributes
-        attributes = set()
-        for customFilter in self.__filterMap:
-            attributes |= set(self.__filterMap[customFilter])
-        
-        # step 2: select all unused attribute items
-        self.attributesList.clearSelection()
-        for row in range(self.attributesList.topLevelItemCount()):
-            itm = self.attributesList.topLevelItem(row)
-            if itm.text(0) not in attributes:
-                itm.setSelected(True)
-    
-    def __removeAttributes(self):
-        """
-        Private method to remove attributes from the Qt Help database.
-        """
-        try:
-            self.__db = sqlite3.connect(self.__engine.collectionFile())
-        except sqlite3.DatabaseError:
-            pass        # ignore database errors
-        
-        for attr in self.__removedAttributes:
-            self.__db.execute(
-                "DELETE FROM FilterAttributeTable WHERE Name = '{0}'"
-                .format(attr))
-        self.__db.commit()
-        self.__db.close()
-    
-    @pyqtSlot()
-    def on_buttonBox_accepted(self):
-        """
-        Private slot to update the database, if the dialog is accepted.
-        """
-        filtersChanged = False
-        if len(self.__filterMapBackup) != len(self.__filterMap):
-            filtersChanged = True
-        else:
-            for customFilter in self.__filterMapBackup:
-                if customFilter not in self.__filterMap:
-                    filtersChanged = True
-                else:
-                    oldFilterAtts = self.__filterMapBackup[customFilter]
-                    newFilterAtts = self.__filterMap[customFilter]
-                    if len(oldFilterAtts) != len(newFilterAtts):
-                        filtersChanged = True
-                    else:
-                        for attr in oldFilterAtts:
-                            if attr not in newFilterAtts:
-                                filtersChanged = True
-                                break
-                
-                if filtersChanged:
-                    break
-        
-        if filtersChanged:
-            for customFilter in self.__removedFilters:
-                self.__engine.removeCustomFilter(customFilter)
-            for customFilter in self.__filterMap:
-                self.__engine.addCustomFilter(
-                    customFilter, self.__filterMap[customFilter])
-        
-        if self.__removedAttributes:
-            self.__removeAttributes()
-        
-        self.accept()
--- a/eric6/WebBrowser/QtHelp/QtHelpFiltersDialog.ui	Tue Sep 10 19:36:17 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>QtHelpFiltersDialog</class>
- <widget class="QDialog" name="QtHelpFiltersDialog">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>570</width>
-    <height>391</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Manage QtHelp Filters</string>
-  </property>
-  <property name="sizeGripEnabled">
-   <bool>true</bool>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <layout class="QGridLayout" name="gridLayout">
-     <item row="0" column="0" colspan="2">
-      <widget class="QLabel" name="label">
-       <property name="text">
-        <string>Filters:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="0" column="2" colspan="2">
-      <widget class="QLabel" name="label_2">
-       <property name="text">
-        <string>Attributes:</string>
-       </property>
-      </widget>
-     </item>
-     <item row="1" column="0" colspan="2">
-      <widget class="QListWidget" name="filtersList">
-       <property name="alternatingRowColors">
-        <bool>true</bool>
-       </property>
-       <property name="selectionMode">
-        <enum>QAbstractItemView::ExtendedSelection</enum>
-       </property>
-       <property name="sortingEnabled">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </item>
-     <item row="1" column="2" colspan="2">
-      <widget class="QTreeWidget" name="attributesList">
-       <property name="alternatingRowColors">
-        <bool>true</bool>
-       </property>
-       <property name="selectionMode">
-        <enum>QAbstractItemView::ExtendedSelection</enum>
-       </property>
-       <property name="rootIsDecorated">
-        <bool>false</bool>
-       </property>
-       <property name="sortingEnabled">
-        <bool>true</bool>
-       </property>
-       <property name="headerHidden">
-        <bool>true</bool>
-       </property>
-       <column>
-        <property name="text">
-         <string>1</string>
-        </property>
-       </column>
-      </widget>
-     </item>
-     <item row="2" column="0">
-      <widget class="QPushButton" name="addButton">
-       <property name="toolTip">
-        <string>Press to add a new filter</string>
-       </property>
-       <property name="text">
-        <string>Add Filter ...</string>
-       </property>
-      </widget>
-     </item>
-     <item row="2" column="1">
-      <widget class="QPushButton" name="removeButton">
-       <property name="toolTip">
-        <string>Press to remove the selected filters</string>
-       </property>
-       <property name="text">
-        <string>Remove Filters</string>
-       </property>
-      </widget>
-     </item>
-     <item row="2" column="2">
-      <widget class="QPushButton" name="removeAttributeButton">
-       <property name="toolTip">
-        <string>Press to remove the selected attributes</string>
-       </property>
-       <property name="text">
-        <string>Remove Attributes</string>
-       </property>
-      </widget>
-     </item>
-     <item row="2" column="3">
-      <widget class="QPushButton" name="unusedAttributesButton">
-       <property name="statusTip">
-        <string>Press to select all unused attributes</string>
-       </property>
-       <property name="text">
-        <string>Select Unused</string>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <tabstops>
-  <tabstop>filtersList</tabstop>
-  <tabstop>addButton</tabstop>
-  <tabstop>removeButton</tabstop>
-  <tabstop>attributesList</tabstop>
-  <tabstop>removeAttributeButton</tabstop>
-  <tabstop>unusedAttributesButton</tabstop>
-  <tabstop>buttonBox</tabstop>
- </tabstops>
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>QtHelpFiltersDialog</receiver>
-   <slot>reject()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>320</x>
-     <y>386</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>286</x>
-     <y>274</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
--- a/eric6/WebBrowser/WebBrowserWindow.py	Tue Sep 10 19:36:17 2019 +0200
+++ b/eric6/WebBrowser/WebBrowserWindow.py	Fri Sep 13 18:54:34 2019 +0200
@@ -1553,20 +1553,6 @@
                 self.__manageQtHelpDocumentation)
             self.__actions.append(self.manageQtHelpDocsAct)
             
-            self.manageQtHelpFiltersAct = E5Action(
-                self.tr('Manage QtHelp Filters'),
-                self.tr('Manage QtHelp &Filters'),
-                0, 0, self, 'webbrowser_qthelp_filters')
-            self.manageQtHelpFiltersAct.setStatusTip(self.tr(
-                'Shows a dialog to manage the QtHelp filters'))
-            self.manageQtHelpFiltersAct.setWhatsThis(self.tr(
-                """<b>Manage QtHelp Filters</b>"""
-                """<p>Shows a dialog to manage the QtHelp filters.</p>"""
-            ))
-            self.manageQtHelpFiltersAct.triggered.connect(
-                self.__manageQtHelpFilters)
-            self.__actions.append(self.manageQtHelpFiltersAct)
-            
             self.reindexDocumentationAct = E5Action(
                 self.tr('Reindex Documentation'),
                 self.tr('&Reindex Documentation'),
@@ -2110,7 +2096,6 @@
         
         if WebBrowserWindow._useQtHelp:
             menu.addAction(self.manageQtHelpDocsAct)
-            menu.addAction(self.manageQtHelpFiltersAct)
             menu.addAction(self.reindexDocumentationAct)
             menu.addSeparator()
         menu.addAction(self.clearPrivateDataAct)
@@ -2231,7 +2216,6 @@
         menu.addSeparator()
         if WebBrowserWindow._useQtHelp:
             menu.addAction(self.manageQtHelpDocsAct)
-            menu.addAction(self.manageQtHelpFiltersAct)
             menu.addAction(self.reindexDocumentationAct)
             menu.addSeparator()
         menu.addAction(self.clearPrivateDataAct)
@@ -3512,9 +3496,10 @@
                 QtHelpDocumentationDialog
             dlg = QtHelpDocumentationDialog(self.__helpEngine, self)
             dlg.exec_()
-            if dlg.hasChanges():
+            if dlg.hasDocumentationChanges():
                 for i in sorted(dlg.getTabsToClose(), reverse=True):
                     self.__tabWidget.closeBrowserAt(i)
+                self.__searchEngine.reindexDocumentation()
         
     def getSourceFileList(self):
         """
@@ -3524,15 +3509,6 @@
         """
         return self.__tabWidget.getSourceFileList()
     
-    def __manageQtHelpFilters(self):
-        """
-        Private slot to manage the QtHelp filters.
-        """
-        if WebBrowserWindow._useQtHelp:
-            from .QtHelp.QtHelpFiltersDialog import QtHelpFiltersDialog
-            dlg = QtHelpFiltersDialog(self.__helpEngine, self)
-            dlg.exec_()
-        
     def __indexingStarted(self):
         """
         Private slot to handle the start of the indexing process.

eric ide

mercurial