2011-03-14 10 views
2

"Editabletreemodel"というpyqt4の優れた例を変更しようとしていますが、私は管理できない問題があります。モデルに新しい行を追加した後、テキストファイルに挿入したデータを保存または更新しますか? 一般に、モデル/ビューのデータをファイルに保存するにはどうすればよいですか?ツリーモデルビューで新しいデータを保存する方法

ありがとうございました。

# This is only needed for Python v2 but is harmless for Python v3. 
import sip 
sip.setapi('QVariant', 2) 

from PyQt4 import QtCore, QtGui 

import editabletreemodel 
from ui_mainwindow import Ui_MainWindow 
import sys, os, time 
import paramiko 
import threading 


class TreeItem(object): 
    def __init__(self, data, parent=None): 
     self.parentItem = parent 
     self.itemData = data 
     self.childItems = [] 

    def child(self, row): 
     return self.childItems[row] 

    def childCount(self): 
     return len(self.childItems) 

    def childNumber(self): 
     if self.parentItem != None: 
      return self.parentItem.childItems.index(self) 
     return 0 

    def columnCount(self): 
     return len(self.itemData) 

    def data(self, column): 
     return self.itemData[column] 

    def insertChildren(self, position, count, columns): 
     if position < 0 or position > len(self.childItems): 
      return False 

     for row in range(count): 
      data = [None for v in range(columns)] 
      item = TreeItem(data, self) 
      self.childItems.insert(position, item) 

     return True 

    def insertColumns(self, position, columns): 
     if position < 0 or position > len(self.itemData): 
      return False 

     for column in range(columns): 
      self.itemData.insert(position, None) 

     for child in self.childItems: 
      child.insertColumns(position, columns) 

     return True 

    def parent(self): 
     return self.parentItem 

    def removeChildren(self, position, count): 
     if position < 0 or position + count > len(self.childItems): 
      return False 

     for row in range(count): 
      self.childItems.pop(position) 

     return True 

    def removeColumns(self, position, columns): 
     if position < 0 or position + columns > len(self.itemData): 
      return False 

     for column in range(columns): 
      self.itemData.pop(position) 

     for child in self.childItems: 
      child.removeColumns(position, columns) 

     return True 

    def setData(self, column, value): 
     if column < 0 or column >= len(self.itemData): 
      return False 

     self.itemData[column] = value 

     return True 


class TreeModel(QtCore.QAbstractItemModel): 
    def __init__(self, headers, data, parent=None): 
     super(TreeModel, self).__init__(parent) 

     rootData = [header for header in headers] 
     self.rootItem = TreeItem(rootData) 
     self.setupModelData(data.split("\n"), self.rootItem) 

    def columnCount(self, parent=QtCore.QModelIndex()): 
     return self.rootItem.columnCount() 

    def data(self, index, role): 
     if not index.isValid(): 
      return None 

     if role != QtCore.Qt.DisplayRole and role != QtCore.Qt.EditRole: 
      return None 

     item = self.getItem(index) 
     return item.data(index.column()) 

    def flags(self, index): 
     if not index.isValid(): 
      return 0 

     return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable 

    def getItem(self, index): 
     if index.isValid(): 
      item = index.internalPointer() 
      if item: 
       return item 

     return self.rootItem 

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole): 
     if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole: 
      return self.rootItem.data(section) 

     return None 

    def index(self, row, column, parent=QtCore.QModelIndex()): 
     if parent.isValid() and parent.column() != 0: 
      return QtCore.QModelIndex() 

     parentItem = self.getItem(parent) 
     childItem = parentItem.child(row) 
     if childItem: 
      return self.createIndex(row, column, childItem) 
     else: 
      return QtCore.QModelIndex() 

    def insertColumns(self, position, columns, parent=QtCore.QModelIndex()): 
     self.beginInsertColumns(parent, position, position + columns - 1) 
     success = self.rootItem.insertColumns(position, columns) 
     self.endInsertColumns() 

     return success 

    def insertRows(self, position, rows, parent=QtCore.QModelIndex()): 
     parentItem = self.getItem(parent) 
     self.beginInsertRows(parent, position, position + rows - 1) 
     success = parentItem.insertChildren(position, rows, 
       self.rootItem.columnCount()) 
     self.endInsertRows() 

     return success 

    def parent(self, index): 
     if not index.isValid(): 
      return QtCore.QModelIndex() 

     childItem = self.getItem(index) 
     parentItem = childItem.parent() 

     if parentItem == self.rootItem: 
      return QtCore.QModelIndex() 

     return self.createIndex(parentItem.childNumber(), 0, parentItem) 

    def removeColumns(self, position, columns, parent=QtCore.QModelIndex()): 
     self.beginRemoveColumns(parent, position, position + columns - 1) 
     success = self.rootItem.removeColumns(position, columns) 
     self.endRemoveColumns() 

     if self.rootItem.columnCount() == 0: 
      self.removeRows(0, rowCount()) 

     return success 

    def removeRows(self, position, rows, parent=QtCore.QModelIndex()): 
     parentItem = self.getItem(parent) 

     self.beginRemoveRows(parent, position, position + rows - 1) 
     success = parentItem.removeChildren(position, rows) 
     self.endRemoveRows() 

     return success 

    def rowCount(self, parent=QtCore.QModelIndex()): 
     parentItem = self.getItem(parent) 

     return parentItem.childCount() 

    def setData(self, index, value, role=QtCore.Qt.EditRole): 
     if role != QtCore.Qt.EditRole: 
      return False 

     item = self.getItem(index) 
     result = item.setData(index.column(), value) 

     if result: 
      self.dataChanged.emit(index, index) 

     return result 

    def setHeaderData(self, section, orientation, value, role=QtCore.Qt.EditRole): 
     if role != QtCore.Qt.EditRole or orientation != QtCore.Qt.Horizontal: 
      return False 

     result = self.rootItem.setData(section, value) 
     if result: 
      self.headerDataChanged.emit(orientation, section, section) 

     return result 

    def setupModelData(self, lines, parent): 
     parents = [parent] 
     indentations = [0] 

     number = 0 

     while number < len(lines): 
      position = 0 
      while position < len(lines[number]): 
       if lines[number][position] != " ": 
        break 
       position += 1 

      lineData = lines[number][position:].trimmed() 

      if lineData: 
       # Read the column data from the rest of the line. 
       columnData = [s for s in lineData.split('\t') if s] 

       if position > indentations[-1]: 
        # The last child of the current parent is now the new 
        # parent unless the current parent has no children. 

        if parents[-1].childCount() > 0: 
         parents.append(parents[-1].child(parents[-1].childCount() - 1)) 
         indentations.append(position) 

       else: 
        while position < indentations[-1] and len(parents) > 0: 
         parents.pop() 
         indentations.pop() 

       # Append a new item to the current parent's list of children. 
       parent = parents[-1] 
       parent.insertChildren(parent.childCount(), 1, 
         self.rootItem.columnCount()) 
       for column in range(len(columnData)): 
        parent.child(parent.childCount() -1).setData(column, columnData[column]) 

      number += 1 


class MainWindow(QtGui.QMainWindow, Ui_MainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 

     self.setupUi(self) 

     headers = ("Sendor Name", "Address", "Comments") 

     file = QtCore.QFile('./default.txt') 
     file.open(QtCore.QIODevice.ReadOnly) 
     model = TreeModel(headers, file.readAll()) 
     file.close() 

     print model.invisibleRootItem() 


     self.view.setModel(model) 
     for column in range(model.columnCount(QtCore.QModelIndex())): 
      self.view.resizeColumnToContents(column) 

     self.exitAction.triggered.connect(QtGui.qApp.quit) 

     self.view.selectionModel().selectionChanged.connect(self.updateActions) 

     self.actionsMenu.aboutToShow.connect(self.updateActions) 
     self.insertRowAction.triggered.connect(self.insertRow) 
     self.insertColumnAction.triggered.connect(self.insertColumn) 
     self.removeRowAction.triggered.connect(self.removeRow) 
     self.removeColumnAction.triggered.connect(self.removeColumn) 
     self.insertChildAction.triggered.connect(self.insertChild) 
     self.callSensorsButton.clicked.connect(self.call_sensors) 

     self.updateActions() 

     self.view.expandAll() 
     self.view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 
     self.view.customContextMenuRequested.connect(self.openMenu) 

     self.connection = connection_thread() 
     self.connect(self.connection, QtCore.SIGNAL("started()"), self.start_progressBar) 
     self.connect(self.connection, QtCore.SIGNAL("finished()"), self.stop_progressBar) 
     self.connect(self.connection, QtCore.SIGNAL("terminated()"), self.stop_progressBar) 

     self.SaveListButton.clicked.connect(self.save_sensor_list) 
     self.pushButton.clicked.connect(self.prova) 


    def save_sensor_list(self): 
     index = self.view.selectionModel().currentIndex() 
     model = self.view.model() 

     print model.rootItem 

     for i in range(0, model.rootItem.rowCount()): 
      print model.child(i) 



    def prova(self): 
     index = self.view.selectionModel().currentIndex() 
     model = self.view.model() 

     print model.data(index,0) 

    def openMenu(self, position): 
     indexes = self.view.selectedIndexes() 
     model = self.view.model() 
     if len(indexes) > 0: 

      level = 0 
      index = indexes[0] 
      while index.parent().isValid(): 
       index = index.parent() 
       level += 1 

     menu = QtGui.QMenu() 
     if level == 0: 
      menu.addAction(self.tr("Call all %ss" % (model.data(index,0)))) 
      menu.addSeparator() 
      menu.addAction(self.tr("Add new sensor family"),self.insertRow) 
      menu.addAction(self.tr("Add new sensor"),self.insertChild) 
     elif level == 1: 
      menu.addAction(self.tr("Call this sensor")) 
      menu.addSeparator() 
      menu.addAction(self.tr("Add new sensor"),self.insertRow) 
     elif level == 2: 
      menu.addAction(self.tr("Edit object")) 

     menu.exec_(self.view.viewport().mapToGlobal(position)) 

    def insertChild(self): 
     index = self.view.selectionModel().currentIndex() 
     model = self.view.model() 

     if model.columnCount(index) == 0: 
      if not model.insertColumn(0, index): 
       return 

     if not model.insertRow(0, index): 
      return 

     for column in range(model.columnCount(index)): 
      child = model.index(0, column, index) 
      model.setData(child, "[No data]", QtCore.Qt.EditRole) 
      if not model.headerData(column, QtCore.Qt.Horizontal).isValid(): 
       model.setHeaderData(column, QtCore.Qt.Horizontal, 
         "[No header]", QtCore.Qt.EditRole) 

     self.view.selectionModel().setCurrentIndex(model.index(0, 0, index), 
       QtGui.QItemSelectionModel.ClearAndSelect) 
     self.updateActions() 

    def insertColumn(self, parent=QtCore.QModelIndex()): 
     model = self.view.model() 
     column = self.view.selectionModel().currentIndex().column() 

     # Insert a column in the parent item. 
     changed = model.insertColumn(column + 1, parent) 
     if changed: 
      model.setHeaderData(column + 1, QtCore.Qt.Horizontal, 
        "[No header]", QtCore.Qt.EditRole) 

     self.updateActions() 

     return changed 

    def insertRow(self): 
     index = self.view.selectionModel().currentIndex() 
     model = self.view.model() 

     if not model.insertRow(index.row()+1, index.parent()): 
      return 

     self.updateActions() 

     for column in range(model.columnCount(index.parent())): 
      child = model.index(index.row()+1, column, index.parent()) 
      model.setData(child, "[No data]", QtCore.Qt.EditRole) 

    def removeColumn(self, parent=QtCore.QModelIndex()): 
     model = self.view.model() 
     column = self.view.selectionModel().currentIndex().column() 

     # Insert columns in each child of the parent item. 
     changed = model.removeColumn(column, parent) 

     if not parent.isValid() and changed: 
      self.updateActions() 

     return changed 

    def removeRow(self): 
     index = self.view.selectionModel().currentIndex() 
     model = self.view.model() 

     if (model.removeRow(index.row(), index.parent())): 
      self.updateActions() 

    def updateActions(self): 
     hasSelection = not self.view.selectionModel().selection().isEmpty() 
     self.removeRowAction.setEnabled(hasSelection) 
     self.removeColumnAction.setEnabled(hasSelection) 

     hasCurrent = self.view.selectionModel().currentIndex().isValid() 
     self.insertRowAction.setEnabled(hasCurrent) 
     self.insertColumnAction.setEnabled(hasCurrent) 

     if hasCurrent: 
      self.view.closePersistentEditor(self.view.selectionModel().currentIndex()) 

      row = self.view.selectionModel().currentIndex().row() 
      column = self.view.selectionModel().currentIndex().column() 
      if self.view.selectionModel().currentIndex().parent().isValid(): 
       self.statusBar().showMessage("Position: (%d,%d)" % (row, column)) 
      else: 
       self.statusBar().showMessage("Position: (%d,%d) in top level" % (row, column)) 

    def start_progressBar(self): 
     self.progressBar.setRange(0,0) 
     self.progressBar.setValue(0) 

    def stop_progressBar(self): 
     self.progressBar.setRange(0,1) 
     self.progressBar.setValue(1) 

    def call_sensors(self): 
     self.textEdit.insertPlainText("Connecting to Fox...\n") 
     self.connection.start_thread(self.textEdit) 


class connection_thread(QtCore.QThread): 
    def __init__(self, parent = None): 
     QtCore.QThread.__init__(self, parent) 

    def start_thread(self,textEdit): 
     self.textEdit = textEdit 
     self.start() 

    def run(self): 
     print "Dentro il thread" 
     time.sleep(10) 
     try: 
      ssh = paramiko.SSHClient() 
      ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
      ssh.connect('192.168.0.90', username='root', password='netusg20') 
      self.textEdit.insertPlainText("Calling sensor list...\n") 
      app.processEvents() 
      stdin, stdout, stderr = ssh.exec_command('python g20.py c') 
      self.textEdit.insertPlainText(stdout.read()) 
      self.textEdit.insertPlainText(stderr.read()) 
      self.textEdit.insertPlainText("Connection closed\n") 
      ssh.close() 
      app.processEvents() 
     except: 
      self.textEdit.insertPlainText(str(sys.exc_info()[1])) 
      ssh.close() 
      app.processEvents() 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = MainWindow() 
    window.show() 
    sys.exit(app.exec_()) 

答えて

2

私はeasiesの方法は、モデルのアイテムものの反復処理し、QDataStreamを経由してファイルに保存保存することだろうと思います。 QDataStreamはQVariantの読み書きをサポートしており、モデルアイテムのデータをQVariantとして取得することができます。以下は小さな例ですが、私は簡単にするためにQStandardItemModelを使用しています:このことができます

import sys 
from PyQt4 import QtGui, QtCore 

class MainForm(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MainForm, self).__init__(parent) 
     self.setMinimumSize(400, 400) 

     # create model 
     self.model = QtGui.QStandardItemModel()   
     for k in range(0, 4): 
      parentItem = self.model.invisibleRootItem() 
      for i in range(0, 4): 
       item = QtGui.QStandardItem(QtCore.QString("item %0 %1").arg(k).arg(i)) 
       parentItem.appendRow(item) 
       parentItem = item 

     # create treeview 
     self.view = QtGui.QTreeView(self) 
     self.view.setModel(self.model) 
     self.view.setMinimumSize(300, 400) 

     self.saveButton = QtGui.QPushButton("save", self) 
     self.saveButton.move(300, 1) 
     self.saveButton.clicked.connect(self.on_save_button_clicked) 

     self.layout = QtGui.QVBoxLayout(self.centralWidget())   
     self.layout.addWidget(self.view) 
     self.layout.addWidget(self.saveButton) 

    def on_save_button_clicked(self): 
     # create text file 
     file = QtCore.QFile("save.txt") 
     file.open(QtCore.QIODevice.WriteOnly) 
     # open data stream 
     out = QtCore.QDataStream(file) 
     # recursively write model item into the datastream 
     self.save_item(self.model.invisibleRootItem(), out) 

    def save_item(self, item, out): 
     for i in range(0, item.rowCount()): 
      child = item.child(i) 
      child.write(out) 
      self.save_item(child, out) 

def main(): 
    app = QtGui.QApplication(sys.argv) 
    form = MainForm() 
    form.show() 
    app.exec_() 

if __name__ == '__main__': 
    main() 

希望を、それは文句を言う、私はなぜ知らない、モデルに沿って繰り返し処理をするのは良いアイデアですが、

+0

についてそれはメソッドinvisibleRootItem()を持たないことを示します。 – Sangi

+0

invisibleRootItem()は、QStandardItemModelのメソッドです。あなたのケースでは、モデルアイテムを反復するためにindex()やdata()などのQAbstractItemModelメソッドを使用する必要があります –

+0

申し訳ありませんが、このItem Model Viewは完全にはクリアされていません。私はすべてのインデックスに沿って反復したいと思いますが、私は反復する必要がある "オブジェクト"についてはわかりません。どのようにして現在のインデックスをインクリメントして次のインデックスに移動できますか? – Sangi

関連する問題