2013-06-08 4 views
7

एक चेक करने योग्य निर्देशिका दृश्य बनाने के प्रयास में, मैंने निम्नलिखित कोड लिखा था। लेकिन चेकबल डिरमोडेल में जब भी कोई एक फ़ोल्डर की जांच करता है, तो उसे जांचने के लिए सभी उप-फ़ोल्डरों पर जाना पड़ता है और यह बहुत धीमा है। मैं उम्मीद कर रहा था कि कोई इस मुद्दे को हल करने में मेरी मदद कर सकता है।PyQt4 चेक करने योग्य निर्देशिका देखें

इस तरह इस एक अभी दिखता है। लेकिन यह धीमा है खासकर अगर कोई एक बड़ा फ़ोल्डर क्लिक करता है।

enter image description here

कोड निष्पादन योग्य है ...

from PyQt4 import QtGui, QtCore 


class CheckableDirModel(QtGui.QDirModel): 
    def __init__(self, parent=None): 
     QtGui.QDirModel.__init__(self, None) 
     self.checks = {} 

    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if role != QtCore.Qt.CheckStateRole: 
      return QtGui.QDirModel.data(self, index, role) 
     else: 
      if index.column() == 0: 
       return self.checkState(index) 

    def flags(self, index): 
     return QtGui.QDirModel.flags(self, index) | QtCore.Qt.ItemIsUserCheckable 

    def checkState(self, index): 
     if index in self.checks: 
      return self.checks[index] 
     else: 
      return QtCore.Qt.Unchecked 

    def setData(self, index, value, role): 
     if (role == QtCore.Qt.CheckStateRole and index.column() == 0): 
      self.checks[index] = value 
      for i in range(self.rowCount(index)): 
       self.setData(index.child(i,0),value,role) 
      return True 

     return QtGui.QDirModel.setData(self, index, value, role) 

    def exportChecked(self, acceptedSuffix=['jpg', 'png', 'bmp']): 
     selection=[] 
     for c in self.checks.keys(): 
      if self.checks[c]==QtCore.Qt.Checked and self.fileInfo(c).completeSuffix().toLower() in acceptedSuffix: 
       try: 

        selection.append(self.filePath(c).toUtf8()) 
       except: 
        pass 
     return selection 

if __name__ == '__main__': 
    import sys 

    app = QtGui.QApplication(sys.argv) 

    model = QtGui.QDirModel() 
    tree = QtGui.QTreeView() 
    tree.setModel(CheckableDirModel()) 

    tree.setAnimated(False) 
    tree.setIndentation(20) 
    tree.setSortingEnabled(True) 

    tree.setWindowTitle("Dir View") 
    tree.resize(640, 480) 
    tree.show() 

    sys.exit(app.exec_()) 

उत्तर

8

आप प्रत्येक फ़ाइल के लिए नहीं की दुकान चेकबॉक्स राज्य अलग कर सकते हैं। उनमें से बहुत से हो सकते हैं। मेरा सुझाव है कि आप निम्न कार्य करना:

आप चेकबॉक्स मानों की सूची रखने के लिए अनुक्रमित उपयोगकर्ता वास्तव में क्लिक किया गया है। जब उपयोगकर्ता कुछ क्लिक करता है, तो आप सूची में एक प्रविष्टि जोड़ते हैं (या यदि यह पहले से मौजूद है तो इसे अपडेट करें), फिर सूची में उपस्थित बच्चों के इंडेक्स के लिए सभी प्रविष्टियों को हटा दें। आपको मूल सूचकांक के डेटा के बारे में एक सिग्नल उत्सर्जित करने की आवश्यकता है और सभी बच्चों की अनुक्रमणिका बदल दी गई है।

जब एक चेकबॉक्स मूल्य (मॉडल के data() फोन करके) का अनुरोध किया है, तो आप सूची में अनुरोध सूचकांक खोजें और उसका मान। यदि सूची सूची में मौजूद नहीं है, तो आप निकटतम मूल सूचकांक की खोज करें और इसके मूल्य को वापस कर दें।

नोट एक तरफ धीमी गति से क्रियान्वित करने से, आपकी कोड में एक और मुद्दा है। जब फ़ाइल पेड़ में बहुत अधिक स्तर होते हैं, तो 'अधिकतम रिकर्सन गहराई पार हो जाती है' अपवाद होता है। मेरे सुझाव को लागू करते समय, इस तरह से रिकर्सन का उपयोग न करें। फ़ाइल पेड़ गहराई लगभग असीमित है।

from collections import deque 

def are_parent_and_child(parent, child): 
    while child.isValid(): 
     if child == parent: 
      return True 
     child = child.parent() 
    return False 


class CheckableDirModel(QtGui.QDirModel): 
    def __init__(self, parent=None): 
     QtGui.QDirModel.__init__(self, None) 
     self.checks = {} 

    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if role == QtCore.Qt.CheckStateRole and index.column() == 0: 
      return self.checkState(index) 
     return QtGui.QDirModel.data(self, index, role) 

    def flags(self, index): 
     return QtGui.QDirModel.flags(self, index) | QtCore.Qt.ItemIsUserCheckable 

    def checkState(self, index): 
     while index.isValid(): 
      if index in self.checks: 
       return self.checks[index] 
      index = index.parent() 
     return QtCore.Qt.Unchecked 

    def setData(self, index, value, role): 
     if role == QtCore.Qt.CheckStateRole and index.column() == 0: 
      self.layoutAboutToBeChanged.emit() 
      for i, v in self.checks.items(): 
       if are_parent_and_child(index, i): 
        self.checks.pop(i) 
      self.checks[index] = value 
      self.layoutChanged.emit() 
      return True 

     return QtGui.QDirModel.setData(self, index, value, role) 

    def exportChecked(self, acceptedSuffix=['jpg', 'png', 'bmp']): 
     selection=set() 
     for index in self.checks.keys(): 
      if self.checks[index] == QtCore.Qt.Checked: 
       for path, dirs, files in os.walk(unicode(self.filePath(index))): 
        for filename in files: 
         if QtCore.QFileInfo(filename).completeSuffix().toLower() in acceptedSuffix: 
          if self.checkState(self.index(os.path.join(path, filename))) == QtCore.Qt.Checked: 
           try: 
            selection.add(os.path.join(path, filename)) 
           except: 
            pass 
    return selection 

मैं dataChanged संकेत का उपयोग करने का विचार है कि सभी बच्चे इंडेक्सों का डेटा बदल दिया गया है सूचित करने के लिए एक तरह से नहीं मिला:

यहाँ कार्यान्वयन है। हम नहीं जानते कि वर्तमान में कौन से इंडेक्स दिखाए जाते हैं, और हम हर बच्चे इंडेक्स के बारे में सूचित नहीं कर सकते क्योंकि यह धीमा हो सकता है। तो मैंने सभी डेटा अपडेट करने के लिए मजबूर करने के लिए layoutAboutToBeChanged और layoutChanged का उपयोग किया। ऐसा लगता है कि यह विधि पर्याप्त तेज़ है।

exportChecked थोड़ा जटिल है। यह अनुकूलित नहीं है, कभी-कभी एक सूचकांक कई बार संसाधित होता है। मैंने डुप्लिकेट फ़िल्टर करने के लिए set() का उपयोग किया है। शायद इसे किसी भी तरह अनुकूलित किया जा सकता है अगर यह बहुत धीमा काम करेगा। हालांकि, अगर उपयोगकर्ता ने कई फाइलों और उपनिर्देशिकाओं के साथ कुछ बड़ी निर्देशिका की जांच की है, तो इस फ़ंक्शन का कोई भी कार्यान्वयन धीमा हो जाएगा। तो अनुकूलन में कोई बात नहीं है, बस इस फ़ंक्शन को अक्सर कॉल न करने का प्रयास करें।

+0

आप कोड कर सकते हैं कि तुम क्या सुझाव दिया ... मैं इनाम – Kiarash

+0

हो गया दर बढ़ाएंगे। यह काम तो ठीक करता है। –

+0

वाह। वह वास्तव में तेज़ है! बहुत बहुत धन्यवाद। बस आखिरी बात, आप चेक किए गए आइटम सूची कैसे प्राप्त करेंगे? निर्यात के समान मूल कोड में चेक किया गया। – Kiarash

संबंधित मुद्दे