def __init__(self, parent): super(QWidget, self).__init__() EventHandler.__init__(self) self.setupUi(self) self.mainwindow = parent.parent.parent.parent self.model = ListNodeModel(self) self.name = self.windowTitle() self.type = "filebrowser" self.setObjectName(self.name) self.vfs = vfs.vfs() self.VFS = VFS.Get() self.loader = loader.loader() self.lmodules = self.loader.modules self.taskmanager = TaskManager() self.parent = parent self.icon = None self.createSubMenu() self.createLayout()
def __init__(self, parent): super(QWidget, self).__init__() EventHandler.__init__(self) self.filterThread = FilterThread(self) self.parent = parent self.vfs = vfs() self.setupUi(self) self.name = self.windowTitle() self.setObjectName(self.name) self.clause_list = [] self.operator_list = [] self.completeClause.setText("") self.__totalnodes = 0 self.__totalhits = 0 self.__processednodes = 0 self.icon = ":search.png" self.translation() self.xtd_attr = PropertyTable(None) self.attrsTree.addWidget(self.xtd_attr) self.model = ListNodeModel(self) self.searchResults = SearchNodeBrowser(self) self.nodeBrowserLayout.addWidget(self.searchResults) self.node_name = QLineEdit() self.node_name.setReadOnly(True) self.nodeBrowserLayout.addWidget(self.node_name) self.searchResults.addTableView() self.searchResults.tableView.setModel(self.model) self.connect(self.searchResults.tableView, SIGNAL("nodeClicked"), self.change_node_name) if QtCore.PYQT_VERSION_STR >= "4.5.0": self.nameContain.textChanged.connect(self.rebuildQuery) self.caseSensitiveName.stateChanged.connect(self.case_sens_changed) self.typeName.currentIndexChanged.connect(self.case_sens_changed) self.launchSearchButton.clicked.connect(self.launchSearch) self.stopSearchButton.clicked.connect(self.stopSearch) self.exportButton.clicked.connect(self.export) else: QtCore.QObject.connect(self.nameContain.textChanged, SIGNAL("clicked(bool)"), self.rebuildQuery) QtCore.QObject.connect(self.caseSensitiveName, SIGNAL("stateChanged(int)"), \ self.case_sens_changed) QtCore.QObject.connect(self.typeName, SIGNAL("currentIndexChanged(int)"), \ self.case_sens_changed) QtCore.QObject.connect(self.launchSearchButton, SIGNAL("clicked(bool)"), self.launchSearch) QtCore.QObject.connect(self.stopSearchButton, SIGNAL("clicked(bool)"), self.stopSearch) QtCore.QObject.connect(self.exportButton, SIGNAL("clicked(bool)"), self.export) self.typeName.addItem("Fixed string", QVariant("f")) self.typeName.addItem("Wildcard", QVariant("w")) self.typeName.addItem("Fuzzy", QVariant("fz")) self.typeName.addItem("Reg exp", QVariant("re")) self.stopSearchButton.hide() self.exportButton.setEnabled(False) self.addedOpt = [] if QtCore.PYQT_VERSION_STR >= "4.5.0": self.addOption.clicked.connect(self.addSearchOptions) else: QtCore.QObject.connect(self.addOption, SIGNAL("clicked(bool)"), self.addSearchOptions) self.connect(self.filterThread, SIGNAL("CountNodes"), self.__progressUpdate) self.connect(self.filterThread, SIGNAL("finished"), self.searchFinished) QtCore.QObject.connect(self.selectAll, SIGNAL("stateChanged(int)"), self.select_all)
class AdvSearch(QWidget, Ui_SearchTab, EventHandler): """ When this widget is instanciated, a new tab is opened in DFF main interface. It contains several sub-widgets used to perform a search by specifying more specifics parameters that the quick search. The tab is devided into two parts :: * The left part is dedicated to a view which is a kind of NodeBrowser designed to display search results. * The right part is a view with several fields used to build the search query. """ def __init__(self, parent): super(QWidget, self).__init__() EventHandler.__init__(self) self.filterThread = FilterThread(self) self.parent = parent self.vfs = vfs() self.setupUi(self) self.name = self.windowTitle() self.setObjectName(self.name) self.clause_list = [] self.operator_list = [] self.completeClause.setText("") self.__totalnodes = 0 self.__totalhits = 0 self.__processednodes = 0 self.icon = ":search.png" self.translation() self.xtd_attr = PropertyTable(None) self.attrsTree.addWidget(self.xtd_attr) self.model = ListNodeModel(self) self.searchResults = SearchNodeBrowser(self) self.nodeBrowserLayout.addWidget(self.searchResults) self.node_name = QLineEdit() self.node_name.setReadOnly(True) self.nodeBrowserLayout.addWidget(self.node_name) self.searchResults.addTableView() self.searchResults.tableView.setModel(self.model) self.connect(self.searchResults.tableView, SIGNAL("nodeClicked"), self.change_node_name) if QtCore.PYQT_VERSION_STR >= "4.5.0": self.nameContain.textChanged.connect(self.rebuildQuery) self.caseSensitiveName.stateChanged.connect(self.case_sens_changed) self.typeName.currentIndexChanged.connect(self.case_sens_changed) self.launchSearchButton.clicked.connect(self.launchSearch) self.stopSearchButton.clicked.connect(self.stopSearch) self.exportButton.clicked.connect(self.export) else: QtCore.QObject.connect(self.nameContain.textChanged, SIGNAL("clicked(bool)"), self.rebuildQuery) QtCore.QObject.connect(self.caseSensitiveName, SIGNAL("stateChanged(int)"), \ self.case_sens_changed) QtCore.QObject.connect(self.typeName, SIGNAL("currentIndexChanged(int)"), \ self.case_sens_changed) QtCore.QObject.connect(self.launchSearchButton, SIGNAL("clicked(bool)"), self.launchSearch) QtCore.QObject.connect(self.stopSearchButton, SIGNAL("clicked(bool)"), self.stopSearch) QtCore.QObject.connect(self.exportButton, SIGNAL("clicked(bool)"), self.export) self.typeName.addItem("Fixed string", QVariant("f")) self.typeName.addItem("Wildcard", QVariant("w")) self.typeName.addItem("Fuzzy", QVariant("fz")) self.typeName.addItem("Reg exp", QVariant("re")) self.stopSearchButton.hide() self.exportButton.setEnabled(False) self.addedOpt = [] if QtCore.PYQT_VERSION_STR >= "4.5.0": self.addOption.clicked.connect(self.addSearchOptions) else: QtCore.QObject.connect(self.addOption, SIGNAL("clicked(bool)"), self.addSearchOptions) self.connect(self.filterThread, SIGNAL("CountNodes"), self.__progressUpdate) self.connect(self.filterThread, SIGNAL("finished"), self.searchFinished) QtCore.QObject.connect(self.selectAll, SIGNAL("stateChanged(int)"), self.select_all) #self.searchBar.setMaximum(100) def __progressUpdate(self, val): self.searchBar.setValue(val) self.__totalhits = self.model.rowCount() self.totalHits.setText(self.currentMatchsText + str(self.__totalhits)) def case_sens_changed(self, state): self.rebuildQuery() def addSearchOptions(self, changed): clause = {} clause_box = BuildSearchClause() ret = clause_box.exec_() if ret: idx = self.typeName.currentIndex() data_type = self.typeName.itemData(idx) for i in range(0, clause_box.advancedOptions.count()): widget = clause_box.advancedOptions.itemAt(i).widget() if not len(widget.edit.text()): continue try: if len(clause[widget.edit.field]): clause[widget.edit.field] += (widget.edit.operator() + " " + widget.edit.field) clause[widget.edit.field] += (widget.edit.text()) except KeyError: clause[widget.edit.field] = (widget.edit.text()) table_clause_widget = SearchClause(self) table_clause_widget.clause_widget.insertColumn(0) table_clause_widget.clause_widget.insertColumn(1) table_clause_widget.clause_widget.horizontalHeader().setStretchLastSection(True) table_clause_widget.clause_widget.horizontalHeader().setFixedHeight(5) if QtCore.PYQT_VERSION_STR >= "4.5.0": table_clause_widget.clause_widget.itemChanged.connect(self.editing_clause) else: QtCore.QObject.connect(self.table_clause_widget.clause_widget,\ SIGNAL("itemChanged(QTableWidgetItem)"), self.editing_clause) nb_line = 0 text = "" if not self.nameContain.text().isEmpty(): text += ("(name (\"" + self.nameContain.text() + ")\"") if not self.caseSensitiveName.isChecked(): text += ",i)" else: text += ")" text += ")" if len(self.clause_list): text += " or " for i in clause: table_clause_widget.clause_widget.insertRow(table_clause_widget.clause_widget.rowCount()) item = QTableWidgetItem(i) item.setFlags(Qt.ItemFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)) item.setToolTip(self.fieldText) table_clause_widget.clause_widget.setItem(table_clause_widget.clause_widget.rowCount() - 1, \ 0, item) item = QTableWidgetItem(clause[i]) item.setFlags(Qt.ItemFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)) item.setToolTip(self.clauseText) table_clause_widget.clause_widget.setItem(table_clause_widget.clause_widget.rowCount() - 1, 1,\ item) table_clause_widget.clause_widget.resizeRowToContents(table_clause_widget.clause_widget.rowCount() - 1) if nb_line == 0: text += ("(" + i + " " + clause[i] + ")") else: text += (" or (" + i + " " + clause[i] + ")") nb_line = nb_line + 1 text += ")" if nb_line: if len(self.clause_list) != 0: if QtCore.PYQT_VERSION_STR >= "4.5.0": table_clause_widget.and_clause.clicked.connect(self.rebuildQuery) table_clause_widget.or_clause.clicked.connect(self.rebuildQuery) else: QtCore.QObject.connect( table_clause_widget.and_clause, SIGNAL("clicked(bool)"), \ self.rebuildQuery) QtCore.QObject.connect( table_clause_widget.or_clause, SIGNAL("clicked(bool)"), \ self.rebuildQuery) else: table_clause_widget.or_clause.hide() table_clause_widget.and_clause.hide() table_clause_widget.bool_operator.deleteLater() # Set height to : (rows amount * row size) + margin + header height, visible to have resize available table_clause_widget.clause_widget.setMaximumHeight((table_clause_widget.clause_widget.rowCount() * \ table_clause_widget.clause_widget.rowHeight(0)) + \ 4 + 5) self.completeClause.setText(text) self.advancedOptions.addWidget(table_clause_widget, self.advancedOptions.rowCount(), 0, Qt.AlignTop) self.clause_list.append(table_clause_widget) self.rebuildQuery() def editing_clause(self, item): self.rebuildQuery() def rebuildQuery(self): text = "" if not self.nameContain.text().isEmpty(): prefix = self.typeName.itemData(self.typeName.currentIndex()).toString() text += ("(name==" + prefix + "(\"" + self.nameContain.text() + "\"") if not self.caseSensitiveName.isChecked(): text += ",i)" else: text += ")" text += ")" if len(self.clause_list): text += " or " for i in range(0, len(self.clause_list)): if i == 0: text += "(" self.clause_list[i].or_clause.hide() self.clause_list[i].and_clause.hide() else: if self.clause_list[i].or_clause.isChecked(): text += " or (" else: text += " and (" clause_widget = self.clause_list[i] for j in range(0, clause_widget.clause_widget.rowCount()): if j != 0: text += " or " text += "(" text += (clause_widget.clause_widget.item(j, 0).text() + " ") text += clause_widget.clause_widget.item(j, 1).text() text += ")" text += ")" self.completeClause.setText(text) def select_all(self, state): checked = Qt.Unchecked if state == Qt.Checked: checked = Qt.Checked nb_row = self.model.rowCount() self.model.emit(SIGNAL("layoutAboutToBeChanged()")) for i in range(0, nb_row): index = self.model.index(i, 0) if not index.isValid(): continue self.model.setData(index, checked, Qt.CheckStateRole) self.model.emit(SIGNAL("layoutChanged()")) def change_node_name(self, button, node): self.node_name.setText(node.absolute()) def searchFinished(self): if self.__totalhits: self.exportButton.setEnabled(True) self.stopSearchButton.hide() self.launchSearchButton.show() def export(self): text, ok = QInputDialog.getText(self, "Advanced search", "Filter export name",\ QLineEdit.Normal, "") if ok and text != "": siNode = self.vfs.getnode("/Searched items") filtersNode = Node(str(text), 0, siNode, None) filtersNode.__disown__() filtersNode.setDir() e = event() e.thisown = False vnode = Variant(filtersNode) vnode.thisown = False e.value = vnode VFS.Get().notify(e) nb_row = self.model.rowCount() for i in range(0, nb_row): index = self.model.index(i, 0) if not index.isValid(): continue data = self.model.data(index, Qt.CheckStateRole) if data == Qt.Checked or data == Qt.PartiallyChecked: n = VFS.Get().getNodeFromPointer(long(index.internalId())) l = VLink(n, filtersNode) l.__disown__() else: box = QMessageBox(QMessageBox.Warning, "Error", "Error node already exists", \ QMessageBox.NoButton, self) box.exec_() def stopSearch(self, changed): self.emit(SIGNAL("stop_search()")) def launchSearch(self, changed): clause = {} self.emit(SIGNAL("NewSearch")) self.__totalhits = 0 self.searchBar.setValue(0) self.totalHits.setText("0 " + self.tr("match(s)")) self.exportButton.setEnabled(False) idx = self.typeName.currentIndex() data_type = self.typeName.itemData(idx) if not self.nameContain.text().isEmpty(): search = str(data_type.toString()) search += ("(\"" + str(self.nameContain.text()) + "\"") if not self.caseSensitiveName.isChecked(): search += ",i)" else: search += ")" clause["name"] = search try: self.filterThread.setContext(self.completeClause.text(), self.vfs.getnode(str(self.path.text()))) self.filterThread.model = self.model self.searchBar.show() self.launchSearchButton.hide() self.stopSearchButton.show() self.totalHits.setText(self.currentMatchsText + "0") self.filterThread.start() except RuntimeError as err: box = QMessageBox(QMessageBox.Warning, self.tr("Invalid clause"), str(err), QMessageBox.Ok, self) box.exec_() def showMoreOptions(self, changed): pass def setCurrentNode(self, path): self.search_in_node = path def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.translation() else: QWidget.changeEvent(self, event) def translation(self): self.fieldText = self.tr("Field") self.clauseText = self.tr("Clause") self.currentMatchsText = self.tr("current match(s): ")
class SearchNodeBrowser(QWidget, EventHandler, Ui_NodeBrowser): def __init__(self, parent): super(QWidget, self).__init__() EventHandler.__init__(self) self.setupUi(self) self.mainwindow = parent.parent.parent.parent self.model = ListNodeModel(self) self.name = self.windowTitle() self.type = "filebrowser" self.setObjectName(self.name) self.vfs = vfs.vfs() self.VFS = VFS.Get() self.loader = loader.loader() self.lmodules = self.loader.modules self.taskmanager = TaskManager() self.parent = parent self.icon = None self.createSubMenu() self.createLayout() def Event(self, e): self.model.emit(SIGNAL("layoutAboutToBeChanged()")) self.model.emit(SIGNAL("layoutChanged()")) def getWindowGeometry(self): self.winWidth = self.mainwindow.width() def createLayout(self): self.baseLayout = QVBoxLayout(self) self.baseLayout.setMargin(0) self.baseLayout.setSpacing(0) self.browserLayout = QSplitter(self) self.baseLayout.insertWidget(0, self.browserLayout) self.baseLayout.setStretchFactor(self.browserLayout, 1) def addNodeView(self): self.addTableView() self.addThumbsView() def addTableView(self): self.tableView = NodeTableView(self) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.setColumnWidth(0, 200) self.tableView.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)) self.browserLayout.addWidget(self.tableView) self.browserLayout.setStretchFactor(self.browserLayout.indexOf(self.tableView), 1) self.connect(self.tableView, SIGNAL("nodePressed"), self.nodePressed) self.connect(self.tableView, SIGNAL("nodeClicked"), self.nodeClicked) self.connect(self.tableView, SIGNAL("nodeDoubleClicked"), self.nodeDoubleClicked) self.connect(self.tableView, SIGNAL(""), self.selectAttr) def applyModule(self, modname, modtype, selected): appMod = ApplyModule(self) appMod.openApplyModule(modname, modtype, selected) def selectAttr(self): pass def addThumbsView(self): self.thumbsView = NodeThumbsView(self) self.thumbsView.setModel(self.model) self.thumbsView.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)) self.browserLayout.addWidget(self.thumbsView) self.browserLayout.setStretchFactor(self.browserLayout.indexOf(self.thumbsView), 1) self.connect(self.thumbsView, SIGNAL("nodePressed"), self.nodePressed) self.connect(self.thumbsView, SIGNAL("nodeClicked"), self.nodeClicked) self.connect(self.thumbsView, SIGNAL("nodeDoubleClicked"), self.nodeDoubleClicked) def currentProxyModel(self): if self.thumbsView.isVisible(): return self.thumbsView.model() elif self.tableView.isVisible(): return self.tableView.model() def currentModel(self): return self.tableView.model() def currentView(self): return self.tableView def currentNodes(self): indexList = self.currentView().selectionModel().selectedRows() nodeList = [] for index in indexList: if index.isValid(): nodeList.append(self.VFS.getNodeFromPointer(index.internalId())) return nodeList def currentNode(self): index = self.currentView().selectionModel().currentIndex() if index.isValid(): return self.VFS.getNodeFromPointer(index.internalId()) def nodePressed(self, key, node, index = None): if key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp, Qt.Key_PageDown]: self.parent.xtd_attr.fill(node) self.mainwindow.emit(SIGNAL("previewUpdate"), node) def nodeClicked(self, mouseButton, node, index = None): if mouseButton == Qt.LeftButton: self.mainwindow.emit(SIGNAL("previewUpdate"), node) if mouseButton == Qt.RightButton: self.menuRelevant = MenuRelevant(self, self, node) if node.hasChildren() or node.isDir(): self.actionOpen_in_new_tab.setEnabled(True) else: self.actionOpen_in_new_tab.setEnabled(False) self.submenuFile.popup(QCursor.pos()) self.submenuFile.show() self.parent.xtd_attr.fill(node) def nodeTreeDoubleClicked(self, mouseButton, node, index = None): if node == None: return if self.currentView().enterInDirectory: if node.hasChildren() or node.isDir(): self.currentModel().setRootPath(node) def nodeDoubleClicked(self, mouseButton, node, index = None): if node == None: return if self.currentView().enterInDirectory: if node.hasChildren() or node.isDir(): self.openAsNewTab() else: self.openDefault(node) else: self.openDefault(node) def sizeChanged(self, string): if self.nodeViewBox.thumbSize.currentIndex() == 0: self.thumbsView.setIconGridSize(64, 64) elif self.nodeViewBox.thumbSize.currentIndex() == 1: self.thumbsView.setIconGridSize(96, 96) elif self.nodeViewBox.thumbSize.currentIndex() == 2: self.thumbsView.setIconGridSize(128, 128) def openDefault(self, node = None): if not node: node = self.currentNode() if not node: return mods = node.compatibleModules() mods.reverse() if len(mods): for mod in mods: if "Viewers" in self.lmodules[mod].tags: break try: priority = modulePriority[mod] except KeyError: modulePriority[mod] = 0 priority = 0 if not priority: mbox = QMessageBox(QMessageBox.Question, self.tr("Apply module"), self.tr("Do you want to apply module ") + str(mod) + self.tr(" on this node ?"), QMessageBox.Yes | QMessageBox.No, self) mbox.addButton(self.tr("Always"), QMessageBox.AcceptRole) reply = mbox.exec_() if reply == QMessageBox.No: return elif reply == QMessageBox.AcceptRole: modulePriority[mod] = 1 if self.lmodules[mod]: conf = self.lmodules[mod].conf arguments = conf.arguments() marg = {} for argument in arguments: if argument.type() == typeId.Node: marg[argument.name()] = node args = conf.generate(marg) self.taskmanager.add(mod, args, ["thread", "gui"]) return else: errnodes = "" if node.size(): conf = self.lmodules["hexadecimal"].conf try: arg = conf.generate({"file": node}) self.taskmanager.add("hexadecimal", arg, ["thread", "gui"]) except RuntimeError: errnodes += node.absolute() + "\n" else: errnodes += node.absolute() + "\n" if len(errnodes): msg = QMessageBox(self) msg.setWindowTitle(self.tr("Empty files")) msg.setText(self.tr("the following nodes could not be opened with Hex viewer because they are either empty or folders\n")) msg.setIcon(QMessageBox.Warning) msg.setDetailedText(errnodes) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def createSubMenu(self): self.extractor = Extractor(self.parent) self.connect(self.extractor, SIGNAL("filled"), self.launchExtract) self.submenuFile = QMenu() self.submenuFile.addAction(self.actionOpen) self.connect(self.actionOpen, SIGNAL("triggered()"), self.openDefault) self.submenuFile.addAction(self.actionOpen_in_new_tab) self.connect(self.actionOpen_in_new_tab, SIGNAL("triggered()"), self.openAsNewTab) self.submenuRelevant = self.submenuFile.addMenu(self.actionRelevant_module.icon(), self.actionRelevant_module.text()) self.menu = {} self.menuModule = self.submenuFile.addMenu(self.actionOpen_with.icon(), self.actionOpen_with.text()) self.menuTags = MenuTags(self, self.parent.parent.parent.parent, self.currentNodes) self.submenuFile.addSeparator() self.submenuFile.addAction(self.actionHex_viewer) self.connect(self.actionHex_viewer, SIGNAL("triggered()"), self.launchHexedit) self.submenuFile.addAction(self.actionExtract) self.connect(self.actionExtract, SIGNAL("triggered()"), self.extractNodes) self.submenuFile.addSeparator() def openAsNewTab(self): node = self.currentNode() self.parent.parent.parent.parent.addNodeBrowser(node) def launchHexedit(self): nodes = self.currentNodes() conf = self.loader.get_conf("hexadecimal") errnodes = "" for node in nodes: if node.size(): try: arg = conf.generate({"file": node}) self.taskmanager.add("hexadecimal", arg, ["thread", "gui"]) except RuntimeError: errnodes += node.absolute() + "\n" else: errnodes += node.absolute() + "\n" if len(errnodes): msg = QMessageBox(self) msg.setWindowTitle(self.tr("Empty files")) msg.setText(self.tr("the following nodes could not be opened with Hex viewer because they are either empty or folders\n")) msg.setIcon(QMessageBox.Warning) msg.setDetailedText(errnodes) msg.setStandardButtons(QMessageBox.Ok) ret = msg.exec_() def extractNodes(self): self.extractor.launch(self.currentNodes()) def launchExtract(self): res = self.extractor.getArgs() args = {} args["files"] = res["nodes"] args["syspath"] = str(res["path"]) args["recursive"] = res["recurse"] conf = self.loader.get_conf("extract") try: margs = conf.generate(args) self.taskmanager.add("extract", margs, ["thread", "gui"]) except RuntimeError: pass def changeEvent(self, event): """ Search for a language change event This event have to call retranslateUi to change interface language on the fly. """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) self.menuModule.setTitle(self.actionOpen_with.text()) self.submenuRelevant.setTitle(self.actionRelevant_module.text()) self.model.translation() else: QWidget.changeEvent(self, event)