Adds: search widget

This commit is contained in:
Olivier Keshavjee 2015-06-30 15:38:14 +02:00
parent 719f6e6fe0
commit 9404a4b92e
9 changed files with 347 additions and 35 deletions

View file

@ -59,9 +59,10 @@ class outlineModel(QAbstractItemModel):
"Returns a list of IDs of all items whose POV is ``POV``." "Returns a list of IDs of all items whose POV is ``POV``."
return self.rootItem.findItemsByPOV(POV) return self.rootItem.findItemsByPOV(POV)
def findItemsContaining(self, text, column): def findItemsContaining(self, text, columns, caseSensitive=False):
"Returns a list of IDs of all items containing ``text`` in column ``column``." """Returns a list of IDs of all items containing ``text``
return self.rootItem.findItemsContaining(text, column) in columns ``columns`` (being a list of int)."""
return self.rootItem.findItemsContaining(text, columns, mainWindow(), caseSensitive)
def getIndexByID(self, ID): def getIndexByID(self, ID):
"Returns the index of item whose ID is ``ID``. If none, returns QModelIndex()." "Returns the index of item whose ID is ``ID``. If none, returns QModelIndex()."
@ -764,15 +765,34 @@ class outlineItem():
return lst return lst
def findItemsContaining(self, text, column): def findItemsContaining(self, text, columns, mainWindow, caseSensitive=False):
"""Returns a list if IDs of all subitems """Returns a list if IDs of all subitems
containing ``text`` in column ``column``. containing ``text`` in columns ``columns``
(being a list of int).
""" """
lst = [] lst = []
if text in self.data(column): text = text.lower() if not caseSensitive else text
lst.append(self.ID()) for c in columns:
if c == Outline.POV.value:
searchIn = mainWindow.mdlPersos.getPersoNameByID(self.POV())
elif c == Outline.status.value:
searchIn = mainWindow.mdlStatus.item(toInt(self.status()), 0).text()
elif c == Outline.label.value:
searchIn = mainWindow.mdlLabels.item(toInt(self.label()), 0).text()
else:
searchIn = self.data(c)
searchIn = searchIn.lower() if not caseSensitive else searchIn
if text in searchIn:
if not self.ID() in lst:
lst.append(self.ID())
for c in self.children(): for c in self.children():
lst.extend(c.findItemsContaining(text, column)) lst.extend(c.findItemsContaining(text, columns, mainWindow, caseSensitive))
return lst return lst

View file

@ -46,7 +46,7 @@ class persosModel(QStandardItemModel):
index = self.getIndexFromID(ID) index = self.getIndexFromID(ID)
if index.isValid(): if index.isValid():
return self.name(index.row()) return self.name(index.row())
return None return ""
def getIndexFromID(self, ID): def getIndexFromID(self, ID):
for i in range(self.rowCount()): for i in range(self.rowCount()):

View file

@ -149,7 +149,7 @@ def infoForRef(ref):
# List scences where character is referenced # List scences where character is referenced
listRefs = "" listRefs = ""
lst = oM.findItemsContaining(ref, Outline.notes.value) lst = oM.findItemsContaining(ref, [Outline.notes.value])
for t in lst: for t in lst:
idx = oM.getIndexByID(t) idx = oM.getIndexByID(t)
listRefs += "<li><a href='{link}'>{text}</a>".format( listRefs += "<li><a href='{link}'>{text}</a>".format(

View file

@ -15,7 +15,7 @@ class cheatSheet(QWidget, Ui_cheatSheet):
def __init__(self, parent=None): def __init__(self, parent=None):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
self.setupUi(self) self.setupUi(self)
self.splitter.setStretchFactor(0, 3) self.splitter.setStretchFactor(0, 5)
self.splitter.setStretchFactor(1, 70) self.splitter.setStretchFactor(1, 70)
self.txtFilter.textChanged.connect(self.updateListFromData) self.txtFilter.textChanged.connect(self.updateListFromData)

View file

@ -844,7 +844,6 @@ class Ui_MainWindow(object):
self.groupBox_3.setFlat(True) self.groupBox_3.setFlat(True)
self.groupBox_3.setObjectName("groupBox_3") self.groupBox_3.setObjectName("groupBox_3")
self.verticalLayout_15 = QtWidgets.QVBoxLayout(self.groupBox_3) self.verticalLayout_15 = QtWidgets.QVBoxLayout(self.groupBox_3)
self.verticalLayout_15.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_15.setObjectName("verticalLayout_15") self.verticalLayout_15.setObjectName("verticalLayout_15")
self.cheatSheet = cheatSheet(self.groupBox_3) self.cheatSheet = cheatSheet(self.groupBox_3)
font = QtGui.QFont() font = QtGui.QFont()
@ -854,6 +853,23 @@ class Ui_MainWindow(object):
self.cheatSheet.setObjectName("cheatSheet") self.cheatSheet.setObjectName("cheatSheet")
self.verticalLayout_15.addWidget(self.cheatSheet) self.verticalLayout_15.addWidget(self.cheatSheet)
self.verticalLayout_21.addWidget(self.groupBox_3) self.verticalLayout_21.addWidget(self.groupBox_3)
self.groupBox_4 = collapsibleGroupBox2(self.tab_18)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.groupBox_4.setFont(font)
self.groupBox_4.setFlat(True)
self.groupBox_4.setObjectName("groupBox_4")
self.verticalLayout_31 = QtWidgets.QVBoxLayout(self.groupBox_4)
self.verticalLayout_31.setObjectName("verticalLayout_31")
self.widget = search(self.groupBox_4)
font = QtGui.QFont()
font.setBold(False)
font.setWeight(50)
self.widget.setFont(font)
self.widget.setObjectName("widget")
self.verticalLayout_31.addWidget(self.widget)
self.verticalLayout_21.addWidget(self.groupBox_4)
self.tabRedacInfos.addTab(self.tab_18, "") self.tabRedacInfos.addTab(self.tab_18, "")
self.verticalLayout_16.addWidget(self.splitterRedac) self.verticalLayout_16.addWidget(self.splitterRedac)
self.tabMain.addTab(self.lytTabRedac, "") self.tabMain.addTab(self.lytTabRedac, "")
@ -1029,7 +1045,7 @@ class Ui_MainWindow(object):
self.stack.setCurrentIndex(1) self.stack.setCurrentIndex(1)
self.tabMain.setCurrentIndex(6) self.tabMain.setCurrentIndex(6)
self.tabSummary.setCurrentIndex(0) self.tabSummary.setCurrentIndex(0)
self.tabPersos.setCurrentIndex(3) self.tabPersos.setCurrentIndex(0)
self.tabPlot.setCurrentIndex(0) self.tabPlot.setCurrentIndex(0)
self.comboBox_2.setCurrentIndex(0) self.comboBox_2.setCurrentIndex(0)
self.stkPlotSummary.setCurrentIndex(0) self.stkPlotSummary.setCurrentIndex(0)
@ -1113,6 +1129,7 @@ class Ui_MainWindow(object):
self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabOutline), _translate("MainWindow", "Outline")) self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabOutline), _translate("MainWindow", "Outline"))
self.tabRedacInfos.setTabText(self.tabRedacInfos.indexOf(self.tab_17), _translate("MainWindow", "Metadata")) self.tabRedacInfos.setTabText(self.tabRedacInfos.indexOf(self.tab_17), _translate("MainWindow", "Metadata"))
self.groupBox_3.setTitle(_translate("MainWindow", "Cheat sheet")) self.groupBox_3.setTitle(_translate("MainWindow", "Cheat sheet"))
self.groupBox_4.setTitle(_translate("MainWindow", "Search"))
self.tabRedacInfos.setTabText(self.tabRedacInfos.indexOf(self.tab_18), _translate("MainWindow", "Tools")) self.tabRedacInfos.setTabText(self.tabRedacInfos.indexOf(self.tab_18), _translate("MainWindow", "Tools"))
self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabRedac), _translate("MainWindow", "Redaction")) self.tabMain.setTabText(self.tabMain.indexOf(self.lytTabRedac), _translate("MainWindow", "Redaction"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_9), _translate("MainWindow", "FlatData")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_9), _translate("MainWindow", "FlatData"))
@ -1152,16 +1169,17 @@ class Ui_MainWindow(object):
self.actSettings.setShortcut(_translate("MainWindow", "F8")) self.actSettings.setShortcut(_translate("MainWindow", "F8"))
self.actCloseProject.setText(_translate("MainWindow", "Close project")) self.actCloseProject.setText(_translate("MainWindow", "Close project"))
from ui.views.treeView import treeView
from ui.editors.mainEditor import mainEditor from ui.editors.mainEditor import mainEditor
from ui.views.persoTreeView import persoTreeView from ui.views.metadataView import metadataView
from ui.sldImportance import sldImportance from ui.search import search
from ui.cheatSheet import cheatSheet
from ui.views.basicItemView import basicItemView
from ui.views.outlineView import outlineView from ui.views.outlineView import outlineView
from ui.collapsibleGroupBox2 import collapsibleGroupBox2 from ui.collapsibleGroupBox2 import collapsibleGroupBox2
from ui.views.metadataView import metadataView from ui.views.persoTreeView import persoTreeView
from ui.views.lineEditView import lineEditView from ui.sldImportance import sldImportance
from ui.views.basicItemView import basicItemView
from ui.views.treeView import treeView
from ui.cheatSheet import cheatSheet
from ui.views.plotTreeView import plotTreeView from ui.views.plotTreeView import plotTreeView
from ui.views.textEditView import textEditView
from ui.welcome import welcome from ui.welcome import welcome
from ui.views.textEditView import textEditView
from ui.views.lineEditView import lineEditView

View file

@ -717,7 +717,7 @@
</widget> </widget>
<widget class="QTabWidget" name="tabPersos"> <widget class="QTabWidget" name="tabPersos">
<property name="currentIndex"> <property name="currentIndex">
<number>3</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="infos"> <widget class="QWidget" name="infos">
<attribute name="title"> <attribute name="title">
@ -1628,9 +1628,6 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_15"> <layout class="QVBoxLayout" name="verticalLayout_15">
<property name="margin">
<number>0</number>
</property>
<item> <item>
<widget class="cheatSheet" name="cheatSheet" native="true"> <widget class="cheatSheet" name="cheatSheet" native="true">
<property name="font"> <property name="font">
@ -1644,6 +1641,34 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="collapsibleGroupBox2" name="groupBox_4">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="title">
<string>Search</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_31">
<item>
<widget class="search" name="widget" native="true">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>
@ -2045,6 +2070,12 @@
<header>ui.collapsibleGroupBox2.h</header> <header>ui.collapsibleGroupBox2.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>search</class>
<extends>QWidget</extends>
<header>ui.search.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections> <connections>
@ -2055,8 +2086,8 @@
<slot>setVisible(bool)</slot> <slot>setVisible(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>325</x> <x>342</x>
<y>787</y> <y>760</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>860</x> <x>860</x>
@ -2087,12 +2118,12 @@
<slot>setVisible(bool)</slot> <slot>setVisible(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1088</x> <x>1136</x>
<y>770</y> <y>768</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>1053</x> <x>1137</x>
<y>731</y> <y>729</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -2135,12 +2166,12 @@
<slot>setVisible(bool)</slot> <slot>setVisible(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>742</x> <x>446</x>
<y>762</y> <y>127</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>742</x> <x>446</x>
<y>749</y> <y>120</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>

150
src/ui/search.py Normal file
View file

@ -0,0 +1,150 @@
#!/usr/bin/env python
#--!-- coding: utf8 --!--
from qt import *
from enums import *
from models.outlineModel import *
from ui.search_ui import *
from functions import *
from models.references import *
class search(QWidget, Ui_search):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setupUi(self)
self.options = {
"All": True,
"Title": True,
"Text": True,
"Summary": False,
"Notes": False,
"POV": False,
"Status": False,
"Label": False,
"CS": True
}
self.text.returnPressed.connect(self.search)
self.generateOptionMenu()
self.delegate = listResultDelegate(self)
self.result.setItemDelegate(self.delegate)
self.result.itemActivated.connect(self.openItem)
def generateOptionMenu(self):
self.menu = QMenu(self)
a = QAction(self.tr("Search in:"), self.menu)
a.setEnabled(False)
self.menu.addAction(a)
for i, d in [
(self.tr("All"), "All"),
(self.tr("Title"), "Title"),
(self.tr("Text"), "Text"),
(self.tr("Summary"), "Summary"),
(self.tr("Notes"), "Notes"),
(self.tr("POV"), "POV"),
(self.tr("Status"), "Status"),
(self.tr("Label"), "Label"),
]:
a = QAction(i, self.menu)
a.setCheckable(True)
a.setChecked(self.options[d])
a.setData(d)
a.triggered.connect(self.updateOptions)
self.menu.addAction(a)
self.menu.addSeparator()
a = QAction(self.tr("Options:"), self.menu)
a.setEnabled(False)
self.menu.addAction(a)
for i, d in [
(self.tr("Case sensitive"), "CS"),
]:
a = QAction(i, self.menu)
a.setCheckable(True)
a.setChecked(self.options[d])
a.setData(d)
a.triggered.connect(self.updateOptions)
self.menu.addAction(a)
self.menu.addSeparator()
self.btnOptions.setMenu(self.menu)
def updateOptions(self):
a = self.sender()
self.options[a.data()] = a.isChecked()
def search(self):
text = self.text.text()
# Chosing the right columns
lstColumns = [
("Title", Outline.title.value),
("Text", Outline.text.value),
("Summary", Outline.summarySentance.value),
("Summary", Outline.summaryFull.value),
("Notes", Outline.notes.value),
("POV", Outline.POV.value),
("Status", Outline.status.value),
("Label", Outline.label.value),
]
columns = [c[1] for c in lstColumns if self.options[c[0]] or self.options["All"]]
# Setting override cursor
qApp.setOverrideCursor(Qt.WaitCursor)
# Searching
model = mainWindow().mdlOutline
results = model.findItemsContaining(text, columns, self.options["CS"])
# Showing results
self.result.clear()
for r in results:
index = model.getIndexByID(r)
if not index.isValid():
continue
item = index.internalPointer()
i = QListWidgetItem(item.title(), self.result)
i.setData(Qt.UserRole, r)
i.setData(Qt.UserRole + 1, item.path())
self.result.addItem(i)
# Removing override cursor
qApp.restoreOverrideCursor()
def openItem(self, item):
mw = mainWindow()
index = mw.mdlOutline.getIndexByID(item.data(Qt.UserRole))
mw.mainEditor.setCurrentModelIndex(index, newTab=True)
class listResultDelegate(QStyledItemDelegate):
def __init__(self, parent=None):
QStyledItemDelegate.__init__(self, parent)
def paint(self, painter, option, index):
extra = index.data(Qt.UserRole+1)
if not extra:
return QStyledItemDelegate.paint(self, painter, option, index)
else:
if option.state & QStyle.State_Selected:
painter.fillRect(option.rect, option.palette.color(QPalette.Highlight))
title = index.data()
extra = " - {}".format(extra)
painter.drawText(option.rect.adjusted(2, 1, 0, 0), Qt.AlignLeft, title)
fm = QFontMetrics(option.font)
w = fm.width(title)
r = QRect(option.rect)
r.setLeft(r.left() + w)
painter.save()
if option.state & QStyle.State_Selected:
painter.setPen(Qt.white)
else:
painter.setPen(Qt.gray)
painter.drawText(r.adjusted(2, 1, 0, 0), Qt.AlignLeft, extra)
painter.restore()

42
src/ui/search_ui.py Normal file
View file

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'src/ui/search_ui.ui'
#
# Created by: PyQt5 UI code generator 5.4.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_search(object):
def setupUi(self, search):
search.setObjectName("search")
search.resize(400, 300)
self.verticalLayout = QtWidgets.QVBoxLayout(search)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.text = QtWidgets.QLineEdit(search)
self.text.setProperty("clearButtonEnabled", True)
self.text.setObjectName("text")
self.horizontalLayout.addWidget(self.text)
self.btnOptions = QtWidgets.QPushButton(search)
self.btnOptions.setText("")
icon = QtGui.QIcon.fromTheme("edit-find")
self.btnOptions.setIcon(icon)
self.btnOptions.setCheckable(True)
self.btnOptions.setObjectName("btnOptions")
self.horizontalLayout.addWidget(self.btnOptions)
self.verticalLayout.addLayout(self.horizontalLayout)
self.result = QtWidgets.QListWidget(search)
self.result.setObjectName("result")
self.verticalLayout.addWidget(self.result)
self.retranslateUi(search)
QtCore.QMetaObject.connectSlotsByName(search)
def retranslateUi(self, search):
_translate = QtCore.QCoreApplication.translate
search.setWindowTitle(_translate("search", "Form"))

51
src/ui/search_ui.ui Normal file
View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>search</class>
<widget class="QWidget" name="search">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="text">
<property name="clearButtonEnabled" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnOptions">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="edit-find"/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="result"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>