Example #1
0
 def createModels(self):
     self.treeModel = TreeModel(self)
     # self.treeModel.coord = True
     self.tableModel = VFSItemModel(self)
     self.treeModel.setRootPath(self.vfs.getnode("/"))
     self.tableModel.setRootPath(self.vfs.getnode("/"))
     self.tableModel.connect(self.navBar, SIGNAL("pathChanged"), self.tableModel.setRootPath)
Example #2
0
    def __init__(self, parent, model):
        """
        Constructor.

        Initialize parent, gui and translation. Connect signals.
        """
        super(QDialog, self).__init__()
        self.parent = parent
        self.setupUi(self)
        self.translation()

        self.initTableWidget()
        self.initMimeTypes()

        self.indexed_items = {}
        self.tmp_indexed_items = {}
        self.un_index = {}

        self.indexedItems.setColumnCount(2)
        self.indexedItems.setRowCount(self.load_items())
        self.model = TreeModel(self)
        self.model.root_item = model.root_item
        self.model.setCh(True)

        self.selectIndexItems = NodeLinkTreeView(None, True)
        self.selectIndexItems.setModel(self.model)
        vbox = QVBoxLayout()
        vbox.addWidget(self.selectIndexItems)
        self.groupBox_5.setLayout(vbox)
        self.connect(self.selectIndexItems, SIGNAL("nodeTreeClicked"), self.nodeTreeClicked)
        self.connect(self.selectIndexItems.model(), SIGNAL("stateChanged"), self.selectNodeChanged)
        self.connect(self.indexedItems, SIGNAL("itemChanged(QTableWidgetItem *)"), \
                         self.IAmBabarTheElephantKing)
        self.connect(self.indexedItems, SIGNAL("itemClicked"), self.IAmBabarTheElephantKing)
Example #3
0
  def addNodeLinkTreeView(self):
    self.treeModel = TreeModel(self, True)
    self.treeModel.setRootPath(self.vfs.getnode("/"))
    self.treeProxyModel = self.treeModel
    self.treeView = NodeLinkTreeView(self)
    self.treeView.setModel(self.treeProxyModel)

    self.browserLayout.addWidget(self.treeView)

    self.browserLayout.setStretchFactor(self.browserLayout.indexOf(self.treeView), 0)

#    self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.nodeTreeDoubleClicked)

    self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.nodeTreeDoubleClicked)
    self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.treeModel.nodeClicked)
Example #4
0
class DialogNodeBrowser(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.title = QLabel("Select a node in the Virtual File System :")
        self.vfs = vfs.vfs()
        self.VFS = VFS.Get()
        self.createLayout()
        self.createModels()
        self.createViews()
        self.createButtons()


    def createLayout(self):
        self.navBar = NavigationBar(self)
        self.baseLayout = QVBoxLayout(self)
        self.baseLayout.setMargin(0)
        self.baseLayout.setSpacing(0)
        self.splitterLayout = QSplitter(self)
        self.splitterLayout.setMinimumWidth(640)
        self.baseLayout.addWidget(self.navBar, 1)
        self.baseLayout.addWidget(self.splitterLayout, 50)
        self.setLayout(self.baseLayout)


    def createModels(self):
        self.treeModel = TreeModel(self)
        # self.treeModel.coord = True
        self.tableModel = VFSItemModel(self)
        self.treeModel.setRootPath(self.vfs.getnode("/"))
        self.tableModel.setRootPath(self.vfs.getnode("/"))
        self.tableModel.connect(self.navBar, SIGNAL("pathChanged"), self.tableModel.setRootPath)


    def createViews(self):
        self.treeView = NodeLinkTreeView(self)
        self.treeView.setModel(self.treeModel)

        self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.nodeTreeClicked)
        self.splitterLayout.addWidget(self.treeView)

        self.tableView = NodeTableView(self)
        self.tableView.setModel(self.tableModel)
        self.connect(self.tableView, SIGNAL("nodeDoubleClicked"), self.nodeDoubleClicked)
        self.splitterLayout.addWidget(self.tableView)


    def nodeTreeClicked(self, mouseButton, node, index = None):
        self.treeView.model().setRootPath(node)
        self.tableView.model().setRootPath(node)
        

    def nodeDoubleClicked(self, mouseButton, node, index = None):
        if node == None:
            return
        if node.hasChildren() or node.isDir():
            self.tableView.model().setRootPath(node)
            self.navBar.updateCurrentPath(node)


    def createButtons(self):
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
        self.connect(self.buttonBox, SIGNAL("accepted()"),self.accept)
        self.connect(self.buttonBox, SIGNAL("rejected()"),self.reject)
        self.baseLayout.addWidget(self.buttonBox)
        

    def getSelectedNodes(self):
        indexes = self.tableView.selectionModel().selectedRows()
        nodes = []
        for index in indexes:
            if index.isValid():
                nodes.append(self.VFS.getNodeFromPointer(index.internalId()))
        return nodes


    def getSelectedNode(self):
        index = self.tableView.selectionModel().currentIndex()
        node = None
        if index.isValid():
            node = self.VFS.getNodeFromPointer(index.internalId())
        return node


    def setSelectionMode(self, mode):
        self.tableView.setSelectionMode(mode)


    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.model.translation()
        else:
            QWidget.changeEvent(self, event)
Example #5
0
class ModifIndex(QDialog, Ui_ModifIndex):
    """
    This class is used to graphically configures indexation :
    * its content
    * its behaviour and the type of data which musts be indexed
    
    It is composed of three tabs : Index, Advanced and Attributes.

    The `Index` tab us composed of two main widgets :
    * a NodeLinkTreeView, called `selectIndexItems`, connected to an instance
    of a TreeModel (see api.gui.model.vfsitemmodel, class TreeModel
    and api.gui.widget.nodeview, class NodeLinkTreeView).

    It displays the tree view of the VFS' nodes, with checkboxes used to select
    nodes the user wants to add in the index.

    * a QTableWidget, called `indexedItems`,  used to summarize the list of
    already indexed nodes.

    By checking / unchecking a nodes in the NodeLinkTreeView, it adds / removes
    elements in the `indexedItems` view. If an element is unchecked and the `OK`
    button clicked, the element will be removed from the index. On the contrary,
    if an element is checked in the NodeLinkTreeView and the `OK` button clicked,
    it will add it in the index ONLY if it was not already indexed.

    Changed are applied when the `OK` button is clicked.
    """
    def __init__(self, parent, model):
        """
        Constructor.

        Initialize parent, gui and translation. Connect signals.
        """
        super(QDialog, self).__init__()
        self.parent = parent
        self.setupUi(self)
        self.translation()

        self.initTableWidget()
        self.initMimeTypes()

        self.indexed_items = {}
        self.tmp_indexed_items = {}
        self.un_index = {}

        self.indexedItems.setColumnCount(2)
        self.indexedItems.setRowCount(self.load_items())
        self.model = TreeModel(self)
        self.model.root_item = model.root_item
        self.model.setCh(True)

        self.selectIndexItems = NodeLinkTreeView(None, True)
        self.selectIndexItems.setModel(self.model)
        vbox = QVBoxLayout()
        vbox.addWidget(self.selectIndexItems)
        self.groupBox_5.setLayout(vbox)
        self.connect(self.selectIndexItems, SIGNAL("nodeTreeClicked"), self.nodeTreeClicked)
        self.connect(self.selectIndexItems.model(), SIGNAL("stateChanged"), self.selectNodeChanged)
        self.connect(self.indexedItems, SIGNAL("itemChanged(QTableWidgetItem *)"), \
                         self.IAmBabarTheElephantKing)
        self.connect(self.indexedItems, SIGNAL("itemClicked"), self.IAmBabarTheElephantKing)

    def initTableWidget(self):
        """
        Initialize the QTableWidget `indexedItems`. Set the headers.
        """
        self.indexedItems.setColumnCount(2)

        # set the headers' titles and stretch the last section
        head1 = QTableWidgetItem(self.headIndexedItemTr)
        head2 = QTableWidgetItem(self.headRecursivelyTr)
        self.indexedItems.setHorizontalHeaderItem(0, head1)
        self.indexedItems.setHorizontalHeaderItem(1, head2)
        self.indexedItems.horizontalHeader().setStretchLastSection(True)

        # hide vertical header and grid, remove editable mode
        self.indexedItems.verticalHeader().hide()
        self.indexedItems.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.indexedItems.setShowGrid(False)
        self.indexedItems.setAlternatingRowColors(True)
        self.indexedItems.setSelectionBehavior(QAbstractItemView.SelectRows)

    def load_items(self):
        """
        Load items from the indexed_items list and add them in the
        self.indexedItems QTableWidget.
        """
        count = 0

        # get the list of already indexed stuff and add them in the qtablewidget
        # with a not-editable check box indicating if it has been indexed
        # recursively or not
        for i in self.indexed_items:
            node = VFS.Get().getNodeFromPointer(long(i))
            if node == None:
                continue
            recurse = self.indexed_items[i]

            new_item = QTableWidgetItem(QIcon(":/folder.png"), node.name())
            self.indexedItems.setRowCount(count + 1)
            new_item.setData(Qt.UserRole + 1, QVariant(long(node.this)))

            self.indexedItems.setItem(count, 0, new_item)

            new_item2 = QTableWidgetItem()
            new_item2.setFlags(Qt.ItemIsUserCheckable)
            if recurse:
                new_item2.setCheckState(Qt.Checked)
            else:
                new_item2.setCheckState(Qt.Unchecked)
            self.indexedItems.setItem(count, 1, new_item2)
            count += 1
        return count

    def initMimeTypes(self):
        self.typesTree = MimeTypesTree(self.mimeTypeList)
        self.mimeTypeList.setHeaderLabels([self.mimeTypeTr])

    def selectNodeChanged(self, index):
        """
        This slot is called when a node is checked / unchecked. Then, the method
        `addNodeInIndexList` or `removeNodeFromIndexList` is called (of course 
        depending if it was checked of unchcked).
        """
        if not index.isValid():
            return
        d = self.selectIndexItems.model().data(index, Qt.CheckStateRole)
        if d == Qt.Checked:
            self.addNodeInIndexList(index)
        else:
            self.removeNodeFromIndexList(index)

    def addNodeInIndexList(self, index):
        """
        Add the node wich pointer is index.data(QT.UserRole + 1) in the
        indexedItems list.
        """
        # get the node from the index
        node_ptr = self.selectIndexItems.model().data(index, Qt.UserRole + 1)
        if not node_ptr.isValid():
            return
        added_node = VFS.Get().getNodeFromPointer(node_ptr.toULongLong()[0])

        # add the node.this into the selected items list
        new_item = QTableWidgetItem(QIcon(":/folder.png"), added_node.name())
        new_item.setData(Qt.UserRole + 1, QVariant(long(added_node.this)))
        self.tmp_indexed_items[long(added_node.this)] = False

        new_checkbox = QTableWidgetItem(1);
        new_checkbox.data(Qt.CheckStateRole);
        new_checkbox.setCheckState(Qt.Unchecked);

        self.indexedItems.insertRow(0)
        self.indexedItems.setItem(0, 0, new_item)
        self.indexedItems.setItem(0, 1, new_checkbox)

    def IAmBabarTheElephantKing(self, item):
        if item.column() == 0:
            return
        row = item.row()
        item_check = self.indexedItems.itemAt(row, 0)
        data = item_check.data(Qt.UserRole + 1)
        if not data.isValid():
            return
        ptr = data.toULongLong()[0]
        try:
            self.tmp_indexed_items[long(ptr)] = not self.tmp_indexed_items[long(ptr)]
        except KeyError:
            pass

    def removeNodeFromIndexList(self, index):
        """
        Remove the node wich pointer is index.data(QT.UserRole + 1) from the
        indexedItems list.
        """
        # get the node from the index (if one of them is invalid, returns)
        if not index.isValid():
            return
        node_ptr = self.selectIndexItems.model().data(index, Qt.UserRole + 1)
        if not node_ptr.isValid():
            return

        # get the ptr of the node and search for the it in the indexedItems list
        ptr = node_ptr.toULongLong()[0]

        # for each items in the indexed_list, check if the value is equal to
        # `ptr`. If yes, remove the item from the QTableWidget self.indexedItems.
        found = False
        for i in range(0, len(self.indexed_items)):
            item = self.indexedItems.item(i, 0)
            if item != None:
                value = item.data(Qt.UserRole + 1)
                if value.isValid():
                    if value.toULongLong()[0] == ptr:
                        self.indexedItems.removeRow(i)
                        self.un_index[ptr] = self.indexed_items[ptr]
                        found = True
                        break

        if not found:
            for i in range(0, len(self.tmp_indexed_items)):
                item = self.indexedItems.item(i, 0)
                if item != None:
                    value = item.data(Qt.UserRole + 1)
                    if value.isValid():
                        if value.toULongLong()[0] == ptr:
                            self.indexedItems.removeRow(i)
                            break

        # finally pop the item from the indexed_items or tmp_indexed_items map
        try:
            if not found:
                self.tmp_indexed_items.pop(ptr)                
        except KeyError:
            pass

    def nodeTreeClicked(self, mouseButton, node, index = None):
        """
        This slot is called when a node from the NodeLinkTreeView is clicked.
        """
        self.selectIndexItems.model().setRootPath(node)

    def translation(self):
        """
        Used for the dynamic translations.
        """
        self.headIndexedItemTr = self.tr("Indexed items")
        self.headRecursivelyTr = self.tr("Recursively")
        self.mimeTypeTr = self.tr("Mime types")
Example #6
0
class NodeBrowser(QWidget, EventHandler, Ui_NodeBrowser):
  def __init__(self, parent):
    super(QWidget, self).__init__()
    EventHandler.__init__(self)
    self.setupUi(self)

    self.mainwindow = parent

    self.getWindowGeometry()

    self.name = self.windowTitle()
    self.type = "filebrowser"
    self.setObjectName(self.name)

    self.vfs = vfs.vfs()
    self.VFS = VFS.Get()
    self.VFS.connection(self)
    self.loader = loader.loader()
    self.lmodules = self.loader.modules
    self.taskmanager = TaskManager()

    self.parent = parent
    self.icon = None

    self.createSubMenu()
    self.createLayout()
    self.addModel("/")

    self.addNodeLinkTreeView()
    self.addNodeView()

    self.addOptionsView()

  def Event(self, e):
    self.model.emit(SIGNAL("layoutAboutToBeChanged()")) 
    self.model.emit(SIGNAL("layoutChanged()"))
    self.treeModel.emit(SIGNAL("layoutAboutToBeChanged()")) 
    self.treeModel.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 addOptionsView(self):
    self.nodeViewBox = NodeViewBox(self)
    self.nodeFilterBox = NodeFilterBox(self, self.treeModel)
    self.nodeFilterBox.vfs_item_model(self.model)
    self.baseLayout.insertWidget(0,self.nodeFilterBox)
    self.baseLayout.insertWidget(0, self.nodeViewBox)
    self.nodeFilterBox.setVisible(False)

  def addModel(self, path):
    self.model = VFSItemModel(self, True, True)
    self.model.setRootPath(self.vfs.getnode(path))

  ###### View searhing #####
  def addSearchView(self):
    self.search_model = VfsSearchItemModel(self, True)
    self.treeModel.setRootPath(self.vfs.getnode("/"))

  def addNodeLinkTreeView(self):
    self.treeModel = TreeModel(self, True)
    self.treeModel.setRootPath(self.vfs.getnode("/"))
    self.treeProxyModel = self.treeModel
    self.treeView = NodeLinkTreeView(self)
    self.treeView.setModel(self.treeProxyModel)

    self.browserLayout.addWidget(self.treeView)

    self.browserLayout.setStretchFactor(self.browserLayout.indexOf(self.treeView), 0)

#    self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.nodeTreeDoubleClicked)

    self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.nodeTreeDoubleClicked)
    self.connect(self.treeView, SIGNAL("nodeTreeClicked"), self.treeModel.nodeClicked)

  def addNodeView(self):
    self.addTableView()
    self.addThumbsView()

  def addTableView(self): 
    self.tableView = NodeTableView(self)

    self.tableView.horizontalHeader().setStretchLastSection(True)
    self.tableView.setModel(self.model)
    self.tableView.setColumnWidth(0, 200)
    self.tableView.setSortingEnabled(True)
    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 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):
     if self.thumbsView.isVisible():
       return self.thumbsView.model() 
     elif self.tableView.isVisible():
       return self.tableView.model() 
 
  def currentView(self):
     if self.thumbsView.isVisible():
       return self.thumbsView
     elif self.tableView.isVisible():
       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]:
      if self.nodeViewBox.propertyTable.isVisible():
        self.nodeViewBox.propertyTable.fill(node)
      self.mainwindow.emit(SIGNAL("previewUpdate"), node)	
    if key == Qt.Key_Return:
      if self.currentView().enterInDirectory:
        if node.hasChildren() or node.isDir():
          self.currentModel().setRootPath(node)
        else:
          self.openDefault(node)
      else:
        self.openDefault(node)
    if key == Qt.Key_Backspace:
      self.currentModel().setRootPath(node.parent().parent())

  def nodeClicked(self, mouseButton, node, index = None):
     if mouseButton == Qt.LeftButton:
         if self.nodeViewBox.propertyTable.isVisible():
            self.nodeViewBox.propertyTable.fill(node)
	 self.mainwindow.emit(SIGNAL("previewUpdate"), node)
     if mouseButton == Qt.RightButton:
       self.menuRelevant = MenuRelevant(self, self.parent, 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()       

  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.currentModel().setRootPath(node) 
      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, 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.mainwindow.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()
      self.treeModel.translation()
    else:
      QWidget.changeEvent(self, event)