예제 #1
0
 def __init__(self, parent=None):
   super(SearchMenu, self).__init__(parent)
   
   self.ui = Ui_SearchMenu()
   self.ui.setupUi(self)
   
   self.ui.shortcutFind = QShortcut(QKeySequence("Ctrl+F"), self)
   self.ui.shortcutFind.activated.connect(self.select_query)
   
   self.ui.txtQuery.setCompleter(None)
   self.ui.txtQuery.setMaxCount(25)
   self.ui.txtQuery.setMaxVisibleItems(25)
   self.ui.txtQuery.setInsertPolicy(QtGui.QComboBox.NoInsert)
   self.ui.txtQuery.view().setTextElideMode(Qt.Qt.ElideNone)
   self.ui.txtQuery.currentIndexChanged.connect(self.select_query)
   
   self.ui.btnFilterSelAll.clicked.connect(lambda: self.filterSetAll(True))
   self.ui.btnFilterSelNone.clicked.connect(lambda: self.filterSetAll(False))
   
   # Unchecked is easier to work with,
   # since it searches everything if nothing's given.
   self.filterSetAll(False)
   
   self.ui.treeResults.setHeaderLabel("Results (0)")
   
   self.ui.actionCopyPath = QtGui.QAction("Copy path", None, triggered = self.copyPath)
   self.ui.treeResults.addAction(self.ui.actionCopyPath)
   
   self.query_re = None
   self.re_flags = re.UNICODE | re.MULTILINE
예제 #2
0
class SearchMenu(QtGui.QDialog):
  ### SIGNALS ###
  open_clicked = pyqtSignal()
  
  def __init__(self, parent=None):
    super(SearchMenu, self).__init__(parent)
    
    self.ui = Ui_SearchMenu()
    self.ui.setupUi(self)
    
    self.ui.shortcutFind = QShortcut(QKeySequence("Ctrl+F"), self)
    self.ui.shortcutFind.activated.connect(self.select_query)
    
    self.ui.txtQuery.setCompleter(None)
    self.ui.txtQuery.setMaxCount(25)
    self.ui.txtQuery.setMaxVisibleItems(25)
    self.ui.txtQuery.setInsertPolicy(QtGui.QComboBox.NoInsert)
    self.ui.txtQuery.view().setTextElideMode(Qt.Qt.ElideNone)
    self.ui.txtQuery.currentIndexChanged.connect(self.select_query)
    
    self.ui.btnFilterSelAll.clicked.connect(lambda: self.filterSetAll(True))
    self.ui.btnFilterSelNone.clicked.connect(lambda: self.filterSetAll(False))
    
    # Unchecked is easier to work with,
    # since it searches everything if nothing's given.
    self.filterSetAll(False)
    
    self.ui.treeResults.setHeaderLabel("Results (0)")
    
    self.ui.actionCopyPath = QtGui.QAction("Copy path", None, triggered = self.copyPath)
    self.ui.treeResults.addAction(self.ui.actionCopyPath)
    
    self.query_re = None
    self.re_flags = re.UNICODE | re.MULTILINE
  
  ##############################################################################
  ### @fn   copyPath()
  ### @desc Copies the path of the selected node to the clipboard.
  ##############################################################################
  def copyPath(self):
    node = self.ui.treeResults.currentItem()
    
    if not node == None:
      text = "{%s}" % tree.tree_item_to_path(node)
      
      clipboard = QApplication.clipboard()
      clipboard.setText(text)
  
  ##############################################################################
  ### @fn   search()
  ### @desc Commences a search.
  ##############################################################################
  def search(self):
    query = common.qt_to_unicode(self.ui.txtQuery.currentText())
    
    self.ui.txtQuery.removeItem(self.ui.txtQuery.findText(query))
    self.ui.txtQuery.insertItem(0, query)
    self.ui.txtQuery.setCurrentIndex(0)
    
    dir = common.editor_config.data01_dir
    
    if query == "":
      results = []
    else:
      results = self.search_bar(query)
      
    self.ui.treeResults.clear()
    self.ui.treeResults.setHeaderLabel("Results (%d)" % len(results))
    
    if len(results) > 0:
      tree_items = []
      
      for file in results:
        file = os.path.normpath(file)
        file = dir_tools.consolidate_dir(file)
        tree_item = tree.path_to_tree(file)
        tree_items.append(tree_item)
      
      tree_items = tree.consolidate_tree_items(tree_items)
      
      for item in tree_items:
        self.ui.treeResults.addTopLevelItem(item)
      
      self.ui.treeResults.expandAll()
    
    self.ui.txtOriginal.clear()
    self.ui.txtTranslated.clear()
    self.ui.txtComments.clear()
    
    self.update_highlights()
  
  ##############################################################################
  ### @fn   search_bar()
  ### @desc Search while displaying a progress bar.
  ##############################################################################
  def search_bar(self, query):
    matches = []
    
    progress = QProgressDialog("", "Abort", 0, 50000, self)
    progress.setWindowTitle("Searching...")
    progress.setWindowModality(Qt.Qt.WindowModal)
    progress.setValue(0)
    progress.setMinimumDuration(0)
    
    width = self.width()
    height = self.height()
    x = self.x()
    y = self.y()
    
    self.re_flags = re.UNICODE | re.MULTILINE
    
    if not self.ui.chkAdvRegex.isChecked():
      query = re.escape(query)
    
    if not self.ui.chkAdvCase.isChecked():
      self.re_flags |= re.IGNORECASE
    
    if self.ui.chkAdvNewline.isChecked():
      self.re_flags |= re.DOTALL
    
    self.query_re = re.compile(query, self.re_flags)
    
    dir_filter  = common.qt_to_unicode(self.ui.txtFilterRe.text())
    if dir_filter == "":
      filter_re = script_analytics.DEFAULT_FILTER
    else:
      filter_re = re.compile(dir_filter, re.IGNORECASE | re.DOTALL | re.UNICODE)
    
    self.search_flags = 0
    if self.ui.chkAdvTrans.isChecked():
      self.search_flags |= script_analytics.SEARCH_TRANSLATED
    if self.ui.chkAdvOrig.isChecked():
      self.search_flags |= script_analytics.SEARCH_ORIGINAL
    if self.ui.chkAdvComments.isChecked():
      self.search_flags |= script_analytics.SEARCH_COMMENTS
    
    if self.ui.chkAdvNoTags.isChecked():
      self.search_flags |= script_analytics.SEARCH_NOTAGS
    
    matches = []
    for i, total, filename, partial_results in script_analytics.SA.search_gen(self.query_re, filter_re, self.search_flags):
      
      if progress.wasCanceled():
        break
      
      progress.setValue(i)
      progress.setMaximum(total)
      progress.setLabelText(filename)
      
      # Re-center the dialog.
      progress_w = progress.geometry().width()
      progress_h = progress.geometry().height()
      
      new_x = x + ((width - progress_w) / 2)
      new_y = y + ((height - progress_h) / 2)
      
      progress.move(new_x, new_y)
      
      matches.extend(partial_results)
    
    progress.close()
    
    return matches
  
  ##############################################################################
  ### @fn   changedSearchFilter()
  ### @desc Triggered when the user clicks one of the search filter checkboxes.
  ##############################################################################
  def changedSearchFilter(self):
    PROLOGUE_RE = ur"e00"
    CH1_RE      = ur"e01"
    CH2_RE      = ur"e02|ldive_s01"
    CH3_RE      = ur"e03"
    CH4_RE      = ur"e04"
    CH5_RE      = ur"e05"
    CH6_RE      = ur"e06"
    EPILOGUE_RE = ur"e07"
    FREETIME_RE = ur"e08_00[1-9]|e08_01[0-5]"
    ISLAND_RE   = ur"e09"
    NOVEL_RE    = ur"novel"
    SYS_RE      = ur"jp\\script\\\d\d|MAP_\d\d\d"
    MISC_RE     = ur"e08_100|e08_150|e08_151|e08_152|event|voice"
    
    # If everything's checked, just leave the regex line blank
    # since blank means we'll search everything.
    all_checked = True
    
    for i in range(self.ui.layoutSearchFilter.count()):
      item = self.ui.layoutSearchFilter.itemAt(i)
      if item and not item.widget().isChecked():
        all_checked = False
        break
    
    if all_checked:
      self.ui.txtFilterRe.clear()
      return
    
    # Otherwise, grab each of the individual checkbox statuses
    # and generate a regex from that.
    active_re   = []
    
    if self.ui.chkSearchPlg.isChecked():
      active_re.append(PROLOGUE_RE)
      
    if self.ui.chkSearchCh1.isChecked():
      active_re.append(CH1_RE)
      
    if self.ui.chkSearchCh2.isChecked():
      active_re.append(CH2_RE)
      
    if self.ui.chkSearchCh3.isChecked():
      active_re.append(CH3_RE)
      
    if self.ui.chkSearchCh4.isChecked():
      active_re.append(CH4_RE)
      
    if self.ui.chkSearchCh5.isChecked():
      active_re.append(CH5_RE)
      
    if self.ui.chkSearchCh6.isChecked():
      active_re.append(CH6_RE)
    
    if self.ui.chkSearchEpg.isChecked():
      active_re.append(EPILOGUE_RE)
    
    if self.ui.chkSearchFt.isChecked():
      active_re.append(FREETIME_RE)
    
    if self.ui.chkSearchIsl.isChecked():
      active_re.append(ISLAND_RE)
    
    if self.ui.chkSearchNvl.isChecked():
      active_re.append(NOVEL_RE)
    
    if self.ui.chkSearchSys.isChecked():
      active_re.append(SYS_RE)
    
    if self.ui.chkSearchEtc.isChecked():
      active_re.append(MISC_RE)
    
    self.ui.txtFilterRe.setText("|".join(active_re))
  
  ##############################################################################
  ### @fn   filterSetAll(checked)
  ### @desc Triggered when the user clicks one of the select all/none buttons.
  ##############################################################################
  def filterSetAll(self, checked):
    if checked:
      state = Qt.Qt.Checked
    else:
      state = Qt.Qt.Unchecked
    
    for i in range(self.ui.layoutSearchFilter.count()):
      item = self.ui.layoutSearchFilter.itemAt(i)
      if item:
        item.widget().setCheckState(state)
  
  ##############################################################################
  ### @fn   doubleClicked()
  ### @desc Triggered when the user double-clicks on an item in the tree.
  ##############################################################################
  def doubleClicked(self, item, column):
    if item.childCount() == 0:
      self.changedSelection(item, None)
      self.accept()
  
  ##############################################################################
  ### @fn   changedSelection()
  ### @desc Triggered when the user selects something in the tree.
  ##############################################################################
  def changedSelection(self, current, prev):
    if current == None or current.childCount() != 0:
      return
    
    file = common.qt_to_unicode(current.text(0))
    path = tree.tree_item_to_path(current.parent())
    path = dir_tools.expand_dir(path)
    
    filename = os.path.join(common.editor_config.data01_dir, path, file)
    
    if not os.path.isfile(filename):
      self.ui.txtTranslated.setPlainText("Could not load \"%s\"." % file)
      self.ui.txtOriginal.setPlainText("")
      self.ui.txtComments.setPlainText("")
      return
    
    script_file = ScriptFile(filename)
    
    notags = self.search_flags & script_analytics.SEARCH_NOTAGS
    
    self.ui.txtTranslated.setPlainText(script_file.notags[common.editor_config.lang_trans] if notags else script_file[common.editor_config.lang_trans])
    self.ui.txtOriginal.setPlainText(script_file.notags[common.editor_config.lang_orig] if notags else script_file[common.editor_config.lang_orig])
    self.ui.txtComments.setPlainText(script_file.comments)
    
    self.update_highlights()
  
  ##############################################################################
  ### @fn   update_highlights()
  ### @desc Updates the highlighted text in the 
  ###       For use when the user presses Ctrl+F or in similar situations.
  ##############################################################################
  def update_highlights(self):
    boxes = [self.ui.txtTranslated, self.ui.txtOriginal, self.ui.txtComments]
    
    for box in boxes:
      selections = []
      text = common.qt_to_unicode(box.toPlainText())
      cursor = QTextCursor(box.document())
      
      base_sel = QTextEdit.ExtraSelection()
      base_sel.cursor = cursor
      base_sel.format.setForeground(QColor(255, 0, 0))
      
      for match in self.query_re.finditer(text):
        sel = QTextEdit.ExtraSelection(base_sel)
        sel.cursor.setPosition(match.start(), QTextCursor.MoveAnchor)
        sel.cursor.setPosition(match.end(), QTextCursor.KeepAnchor)
        selections.append(sel)
      
      box.setExtraSelections(selections)
  
  ##############################################################################
  ### @fn   select_query()
  ### @desc Selects the query and gives the box focus.
  ###       For use when the user presses Ctrl+F or in similar situations.
  ##############################################################################
  def select_query(self):
    self.ui.txtQuery.setFocus(Qt.Qt.OtherFocusReason)
    self.ui.txtQuery.lineEdit().selectAll()
  
  ##############################################################################
  ### @fn   accept()
  ### @desc Overrides the OK button to make sure a folder is selected.
  ##############################################################################
  def accept(self):
    if self.ui.treeResults.currentItem() == None or self.ui.treeResults.currentItem().childCount() != 0:
      return
    self.open_clicked.emit()
  
  ##############################################################################
  ### @fn   show()
  ### @desc Overrides the show routine to place the cursor in the search box.
  ##############################################################################
  def show(self):
    self.select_query()
    super(SearchMenu, self).show()