Exemplo n.º 1
0
    def select(self, selection, flags):
        if isinstance(selection, QModelIndex):
            selection = QItemSelection(selection, selection)

        model = self.model()
        indexes = selection.indexes()
        sel_inds = {ind.row() for ind in indexes} | \
                   {ind.column() for ind in indexes}
        if flags == QItemSelectionModel.ClearAndSelect:
            selected = set()
        else:
            selected = {ind.row() for ind in self.selectedIndexes()}
        if flags & QItemSelectionModel.Select:
            selected |= sel_inds
        elif flags & QItemSelectionModel.Deselect:
            selected -= sel_inds
        new_selection = QItemSelection()
        regions = list(ranges(sorted(selected)))
        for r_start, r_end in regions:
            for c_start, c_end in regions:
                top_left = model.index(r_start, c_start)
                bottom_right = model.index(r_end - 1, c_end - 1)
                new_selection.select(top_left, bottom_right)
        QItemSelectionModel.select(self, new_selection,
                                   QItemSelectionModel.ClearAndSelect)
Exemplo n.º 2
0
    def select(self, selection, flags):
        if isinstance(selection, QModelIndex):
            selection = QItemSelection(selection, selection)

        model = self.model()
        indexes = selection.indexes()
        sel_inds = {ind.row() for ind in indexes} | \
                   {ind.column() for ind in indexes}
        if flags == QItemSelectionModel.ClearAndSelect:
            selected = set()
        else:
            selected = {ind.row() for ind in self.selectedIndexes()}
        if flags & QItemSelectionModel.Select:
            selected |= sel_inds
        elif flags & QItemSelectionModel.Deselect:
            selected -= sel_inds
        new_selection = QItemSelection()
        regions = list(ranges(sorted(selected)))
        for r_start, r_end in regions:
            for c_start, c_end in regions:
                top_left = model.index(r_start, c_start)
                bottom_right = model.index(r_end - 1, c_end - 1)
                new_selection.select(top_left, bottom_right)
        QItemSelectionModel.select(self, new_selection,
                                   QItemSelectionModel.ClearAndSelect)
Exemplo n.º 3
0
    def __init__(self, elements=None, parent=None):
        '''
        Common interface for the labelListModel and the boxListModel
        see concrete implementations for details

        :param elements:
        :param parent:
        '''
        QAbstractTableModel.__init__(self, parent)

        if elements is None:
            elements = []
        self._elements = list(elements)
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):


            if selected:
                ind = selected[0].indexes()
                if len(ind)>0:
                    self.elementSelected.emit(ind[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}

        self.unremovable_rows=[] #rows in this list cannot be removed from the gui,
Exemplo n.º 4
0
 def __init__(self, parent=None):
     QAbstractListModel.__init__(self, parent)
     self._layerStack = []
     self.selectionModel = QItemSelectionModel(self)
     self.selectionModel.selectionChanged.connect(self.updateGUI)
     self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
     self._movingRows = False
     QTimer.singleShot(0, self.updateGUI)
Exemplo n.º 5
0
 def onAnnotationsLoaded(self):
     self.labeltool.model().dirtyChanged.connect(self.onModelDirtyChanged)
     self.onModelDirtyChanged(self.labeltool.model().dirty())
     self.treeview.setModel(self.labeltool.model())
     self.scene.setModel(self.labeltool.model())
     self.selectionmodel = QItemSelectionModel(self.labeltool.model())
     self.treeview.setSelectionModel(self.selectionmodel)
     self.treeview.selectionModel().currentChanged.connect(self.labeltool.setCurrentImage)
     self.property_editor.onModelChanged(self.labeltool.model())
     self.startBackgroundLoading()
Exemplo n.º 6
0
    def select(self, selection, flags):
        """Reimplemented."""
        if isinstance(selection, QModelIndex):
            selection = QtGui.QItemSelection(selection, selection)

        model = self.model()
        indexes = self.selectedIndexes()

        rows = set(ind.row() for ind in indexes)
        cols = set(ind.column() for ind in indexes)

        if flags & QItemSelectionModel.Select and \
                not flags & QItemSelectionModel.Clear and self.__selectBlocks:
            indexes = selection.indexes()
            sel_rows = set(ind.row() for ind in indexes).union(rows)
            sel_cols = set(ind.column() for ind in indexes).union(cols)

            selection = QtGui.QItemSelection()

            for r_start, r_end in ranges(sorted(sel_rows)):
                for c_start, c_end in ranges(sorted(sel_cols)):
                    top_left = model.index(r_start, c_start)
                    bottom_right = model.index(r_end - 1, c_end - 1)
                    selection.select(top_left, bottom_right)
        elif self.__selectBlocks and flags & QItemSelectionModel.Deselect:
            indexes = selection.indexes()

            def to_ranges(indices):
                return list(range(*r) for r in ranges(indices))

            selected_rows = to_ranges(sorted(rows))
            selected_cols = to_ranges(sorted(cols))

            desel_rows = to_ranges(set(ind.row() for ind in indexes))
            desel_cols = to_ranges(set(ind.column() for ind in indexes))

            selection = QtGui.QItemSelection()

            # deselection extended vertically
            for row_range, col_range in \
                    itertools.product(selected_rows, desel_cols):
                selection.select(
                    model.index(row_range.start, col_range.start),
                    model.index(row_range.stop - 1, col_range.stop - 1)
                )
            # deselection extended horizontally
            for row_range, col_range in \
                    itertools.product(desel_rows, selected_cols):
                selection.select(
                    model.index(row_range.start, col_range.start),
                    model.index(row_range.stop - 1, col_range.stop - 1)
                )

        QItemSelectionModel.select(self, selection, flags)
Exemplo n.º 7
0
    def select(self, selection, flags):
        """Reimplemented."""
        if isinstance(selection, QModelIndex):
            selection = QtGui.QItemSelection(selection, selection)

        model = self.model()
        indexes = self.selectedIndexes()

        rows = set(ind.row() for ind in indexes)
        cols = set(ind.column() for ind in indexes)

        if flags & QItemSelectionModel.Select and \
                not flags & QItemSelectionModel.Clear and self.__selectBlocks:
            indexes = selection.indexes()
            sel_rows = set(ind.row() for ind in indexes).union(rows)
            sel_cols = set(ind.column() for ind in indexes).union(cols)

            selection = QtGui.QItemSelection()

            for r_start, r_end in ranges(sorted(sel_rows)):
                for c_start, c_end in ranges(sorted(sel_cols)):
                    top_left = model.index(r_start, c_start)
                    bottom_right = model.index(r_end - 1, c_end - 1)
                    selection.select(top_left, bottom_right)
        elif self.__selectBlocks and flags & QItemSelectionModel.Deselect:
            indexes = selection.indexes()

            def to_ranges(indices):
                return list(range(*r) for r in ranges(indices))

            selected_rows = to_ranges(sorted(rows))
            selected_cols = to_ranges(sorted(cols))

            desel_rows = to_ranges(set(ind.row() for ind in indexes))
            desel_cols = to_ranges(set(ind.column() for ind in indexes))

            selection = QtGui.QItemSelection()

            # deselection extended vertically
            for row_range, col_range in \
                    itertools.product(selected_rows, desel_cols):
                selection.select(
                    model.index(row_range.start, col_range.start),
                    model.index(row_range.stop - 1, col_range.stop - 1)
                )
            # deselection extended horizontally
            for row_range, col_range in \
                    itertools.product(desel_rows, selected_cols):
                selection.select(
                    model.index(row_range.start, col_range.start),
                    model.index(row_range.stop - 1, col_range.stop - 1)
                )

        QItemSelectionModel.select(self, selection, flags)
    def __init__(self, labels=[], parent=None):
        QAbstractTableModel.__init__(self, parent)
        self._labels = labels
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):
            if selected:
                self.labelSelected.emit(selected[0].indexes()[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}
Exemplo n.º 9
0
    def __setRowSelected(self, index, selected=True):
        " Selects a row "
        if not index.isValid():
            return

        if selected:
            flags = QItemSelectionModel.SelectionFlags(
                QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
        else:
            flags = QItemSelectionModel.SelectionFlags(
                QItemSelectionModel.Deselect | QItemSelectionModel.Rows)
        self.selectionModel().select(index, flags)
        return
Exemplo n.º 10
0
    def __init__(self, parent=None):
        super(Games, self).__init__(parent)
        self.selectedGame = None
        self.onlyPending = True
        self.setWindowTitle(m18nc('kajongg', 'Games') + ' - Kajongg')
        self.setObjectName('Games')
        self.resize(700, 400)
        self.model = GamesModel(self)
        if Debug.modelTest:
            self.modelTest = ModelTest(self.model, self)

        self.view = MJTableView(self)
        self.view.setModel(self.model)
        self.selection = QItemSelectionModel(self.model, self.view)
        self.view.setSelectionModel(self.selection)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.view.setSelectionMode(QAbstractItemView.SingleSelection)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.newButton = self.buttonBox.addButton(
            m18nc('start a new game', "&New"), QDialogButtonBox.ActionRole)
        self.newButton.setIcon(KIcon("document-new"))
        self.newButton.clicked.connect(self.accept)
        self.loadButton = self.buttonBox.addButton(m18n("&Load"),
                                                   QDialogButtonBox.AcceptRole)
        self.loadButton.clicked.connect(self.loadGame)
        self.loadButton.setIcon(KIcon("document-open"))
        self.deleteButton = self.buttonBox.addButton(
            m18n("&Delete"), QDialogButtonBox.ActionRole)
        self.deleteButton.setIcon(KIcon("edit-delete"))
        self.deleteButton.clicked.connect(self.delete)

        chkPending = QCheckBox(m18n("Show only pending games"), self)
        chkPending.setChecked(True)
        cmdLayout = QHBoxLayout()
        cmdLayout.addWidget(chkPending)
        cmdLayout.addWidget(self.buttonBox)

        layout = QVBoxLayout()
        layout.addWidget(self.view)
        layout.addLayout(cmdLayout)
        self.setLayout(layout)
        StateSaver(self)

        self.selection.selectionChanged.connect(self.selectionChanged)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.view.doubleClicked.connect(self.loadGame)
        chkPending.stateChanged.connect(self.pendingOrNot)
Exemplo n.º 11
0
    def __init__(self, parent=None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.updateGUI)
        self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
        self._movingRows = False
        QTimer.singleShot(0, self.updateGUI)

        def _handleRemovedLayer(layer):
            # Layerstacks *own* the layers they hold, and thus are
            #  responsible for cleaning them up when they are removed:
            layer.clean_up()

        self.layerRemoved.connect(_handleRemovedLayer)
Exemplo n.º 12
0
 def __init__(self, parent = None):
     QAbstractListModel.__init__(self, parent)
     self._layerStack = []
     self.selectionModel = QItemSelectionModel(self)
     self.selectionModel.selectionChanged.connect(self.updateGUI)
     self._movingRows = False
     QTimer.singleShot(0, self.updateGUI)
Exemplo n.º 13
0
    def __init__(self, elements=None, parent=None):
        '''
        Common interface for the labelListModel and the boxListModel
        see concrete implementations for details

        :param elements:
        :param parent:
        '''
        QAbstractTableModel.__init__(self, parent)

        if elements is None:
            elements = []
        self._elements = list(elements)
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):


            if selected:
                ind = selected[0].indexes()
                if len(ind)>0:
                    self.elementSelected.emit(ind[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}

        self.unremovable_rows=[] #rows in this list cannot be removed from the gui,
Exemplo n.º 14
0
 def onAnnotationsLoaded(self):
     self.labeltool.model().dirtyChanged.connect(self.onModelDirtyChanged)
     self.onModelDirtyChanged(self.labeltool.model().dirty())
     self.treeview.setModel(self.labeltool.model())
     self.scene.setModel(self.labeltool.model())
     self.selectionmodel = QItemSelectionModel(self.labeltool.model())
     self.treeview.setSelectionModel(self.selectionmodel)
     self.treeview.selectionModel().currentChanged.connect(self.labeltool.setCurrentImage)
     self.property_editor.onModelChanged(self.labeltool.model())
     self.startBackgroundLoading()
Exemplo n.º 15
0
 def __init__(self, labels = [], parent = None):
     QAbstractTableModel.__init__(self, parent)
     self._labels = labels
     self._selectionModel = QItemSelectionModel(self)
     
     def onSelectionChanged(selected, deselected):
         if selected:
             self.labelSelected.emit(selected[0].indexes()[0].row())
     self._selectionModel.selectionChanged.connect(onSelectionChanged)
     
     self._allowRemove = True
Exemplo n.º 16
0
 def __init__(self, parent=None, name=None, editable=False):
     QComboBox.__init__(self, parent)
     self.setMaxVisibleItems(20)
     self.setEditable(editable)
     self.maxWidth = 0
     if name is not None:
         self.setObjectName(name)
     # save the model, use our view, create a new selection model
     model = self.model()
     oldview = self.view()
     self.setView(ComboListView(self, self))
     self.view().setModel(model)
     self.view().setSelectionModel(QItemSelectionModel(model, self.view()))
Exemplo n.º 17
0
 def setupTables(self):
     """
         Initialize all the application tablesview
     """
     self.cTableView.setModel(self.cModel)
     self.cTableView.setItemDelegate(MyQSqlRelationalDelegate(self))
     self.cTableView.setColumnHidden(CID, True)
     self.cTableView.setWordWrap(True)
     self.cTableView.resizeRowsToContents()
     self.cTableView.setAlternatingRowColors(True)
     self.cItmSelModel = QItemSelectionModel(self.cModel)
     self.cTableView.setSelectionModel(self.cItmSelModel)
     self.cTableView.setSelectionBehavior(QTableView.SelectRows)
     self.cTableView.setSortingEnabled(True)
Exemplo n.º 18
0
 def __init__(self, parent = None):
     QAbstractListModel.__init__(self, parent)
     self._layerStack = []
     self.selectionModel = QItemSelectionModel(self)
     self.selectionModel.selectionChanged.connect(self.updateGUI)
     self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
     self._movingRows = False
     QTimer.singleShot(0, self.updateGUI)
     
     def _handleRemovedLayer(layer):
         # Layerstacks *own* the layers they hold, and thus are 
         #  responsible for cleaning them up when they are removed:
         layer.clean_up()
     self.layerRemoved.connect( _handleRemovedLayer )
Exemplo n.º 19
0
    def __init__(self, labels=None, parent=None):
        QAbstractTableModel.__init__(self, parent)

        if labels is None:
            labels = []
        self._labels = list(labels)
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):
            if selected:
                self.labelSelected.emit(selected[0].indexes()[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}
Exemplo n.º 20
0
  def __init__(self):
    super(Window, self).__init__()

    central_widget = QWidget()

    self._current_path = None
    self._use_suffix = False

    self._file_model = QFileSystemModel()
    self._file_model.setNameFilters(['*.jpg', '*.png'])
    self._file_model.setNameFilterDisables(False)
    self._file_model.setRootPath(QDir.rootPath())

    self._file_selection_model = QItemSelectionModel(self._file_model)
    self._file_selection_model.currentChanged.connect(self._on_current_file_changed)

    self._file_tree = QTreeView(parent=self)
    self._file_tree.collapsed.connect(self._on_tree_expanded_collapsed)
    self._file_tree.expanded.connect(self._on_tree_expanded_collapsed)
    self._file_tree.setModel(self._file_model)
    self._file_tree.setSelectionModel(self._file_selection_model)
    self._file_tree.setColumnHidden(1, True)
    self._file_tree.setColumnHidden(2, True)
    self._file_tree.setColumnHidden(3, True)
    self._file_tree.header().hide()

    self._viewer = Viewer(Loader(24))

    self._splitter = QSplitter();
    self._splitter.addWidget(self._file_tree)
    self._splitter.addWidget(self._viewer)
    self._splitter.setStretchFactor(0, 0)
    self._splitter.setStretchFactor(1, 1)
    self._splitter.setCollapsible(0, False)

    self._layout = QGridLayout()
    self._layout.addWidget(self._splitter)
    self._switch_to_normal()
    central_widget.setLayout(self._layout)

    self._file_tree.installEventFilter(self);

    self.resize(800, 600)
    self.setWindowTitle('pyQtures')
    self.setCentralWidget(central_widget)
    self.show()
Exemplo n.º 21
0
 def __init__(self, parent):
     QtGui.QDialog.__init__(self)
     self.ui = Ui_IMDBSearchDialog()
     self.ui.setupUi(self)
     self._main  = parent
     
     QObject.connect(self.ui.searchMovieButton, SIGNAL("clicked(bool)"), self.onSearchMovieButton)
     QObject.connect(self.ui.movieInfoButton, SIGNAL("clicked(bool)"), self.onMovieInfoButton)
     QObject.connect(self.ui.okButton, SIGNAL("clicked(bool)"), self.onOkButton)
     QObject.connect(self.ui.cancelButton, SIGNAL("clicked(bool)"), self.onCancelButton)
     
     header = self.ui.searchResultsView.horizontalHeader()
     header.setResizeMode(QtGui.QHeaderView.Stretch)
     header.hide()
     self.ui.searchResultsView.verticalHeader().hide()
     
     self.imdbModel = ImdbListModel(self)
     self.ui.searchResultsView.setModel(self.imdbModel)
     self.imdbModel._main = self #FIXME: This connection should be cleaner.
     self.imdbSelectionModel = QItemSelectionModel(self.imdbModel)
     self.ui.searchResultsView.setSelectionModel(self.imdbSelectionModel)
     QObject.connect(self.imdbSelectionModel, SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), self.onIMDBChangeSelection)
     QObject.connect(self.ui.searchResultsView, SIGNAL("activated(QModelIndex)"), self.onOkButton)
Exemplo n.º 22
0
 def loadTables(self, tables):
     """build and use a model around the tables.
     Show all new tables (no gameid given yet) and all suspended
     tables that also exist locally. In theory all suspended games should
     exist locally but there might have been bugs or somebody might
     have removed the local database like when reinstalling linux"""
     if not Internal.field:
         return
     if Debug.traffic:
         for table in tables:
             if table.gameid and not table.gameExistsLocally():
                 logDebug('%s does not exist locally' % table)
     tables = [x for x in tables if not x.gameid or x.gameExistsLocally()]
     tables.sort(key=lambda x: x.tableid)
     preselectTableId = self.__preselectTableId(tables)
     self.__keepChatWindows(tables)
     model = TablesModel(tables)
     self.view.setModel(model)
     if Debug.modelTest:
         self.debugModelTest = ModelTest(model, self.view)
     selection = QItemSelectionModel(model, self.view)
     self.view.initView()
     self.view.setSelectionModel(selection)
     self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
     self.view.setSelectionMode(QAbstractItemView.SingleSelection)
     selection.selectionChanged.connect(self.selectionChanged)
     if len(tables) == 1:
         self.selectTable(0)
         self.startButton.setFocus()
     elif not tables:
         self.newButton.setFocus()
     else:
         _ = [x for x in tables if x.tableid >= preselectTableId]
         self.selectTable(tables.index(_[0]) if _ else 0)
     self.updateButtonsForTable(self.selectedTable())
     self.view.setFocus()
Exemplo n.º 23
0
    def setupTables(self):
        """
            Initialize all the application tablesview
        """
        self.sTableView.setModel(self.sModel)
        self.sTableView.setItemDelegate(MSDelegate(self))
        self.sTableView.setColumnHidden(ID, True)
        self.sTableView.setColumnHidden(MMID, True)
        self.sTableView.setWordWrap(True)
        self.sTableView.resizeRowsToContents()
        self.sTableView.setAlternatingRowColors(True)
        self.sItmSelModel = QItemSelectionModel(self.sModel)
        self.sTableView.setSelectionModel(self.sItmSelModel)
        self.sTableView.setSelectionBehavior(QTableView.SelectRows)
        #self.sTableView.setTabKeyNavigation(True)


        self.fTableView.setModel(self.fModel)
        self.fTableView.setColumnHidden(ID, True)
        self.fTableView.setWordWrap(True)
        self.fTableView.resizeRowsToContents()
        self.fTableView.setAlternatingRowColors(True)
        self.fItmSelModel = QItemSelectionModel(self.fModel)
        self.fTableView.setSelectionModel(self.fItmSelModel)
Exemplo n.º 24
0
class Window(QMainWindow):

  def __init__(self):
    super(Window, self).__init__()

    central_widget = QWidget()

    self._current_path = None
    self._use_suffix = False

    self._file_model = QFileSystemModel()
    self._file_model.setNameFilters(['*.jpg', '*.png'])
    self._file_model.setNameFilterDisables(False)
    self._file_model.setRootPath(QDir.rootPath())

    self._file_selection_model = QItemSelectionModel(self._file_model)
    self._file_selection_model.currentChanged.connect(self._on_current_file_changed)

    self._file_tree = QTreeView(parent=self)
    self._file_tree.collapsed.connect(self._on_tree_expanded_collapsed)
    self._file_tree.expanded.connect(self._on_tree_expanded_collapsed)
    self._file_tree.setModel(self._file_model)
    self._file_tree.setSelectionModel(self._file_selection_model)
    self._file_tree.setColumnHidden(1, True)
    self._file_tree.setColumnHidden(2, True)
    self._file_tree.setColumnHidden(3, True)
    self._file_tree.header().hide()

    self._viewer = Viewer(Loader(24))

    self._splitter = QSplitter();
    self._splitter.addWidget(self._file_tree)
    self._splitter.addWidget(self._viewer)
    self._splitter.setStretchFactor(0, 0)
    self._splitter.setStretchFactor(1, 1)
    self._splitter.setCollapsible(0, False)

    self._layout = QGridLayout()
    self._layout.addWidget(self._splitter)
    self._switch_to_normal()
    central_widget.setLayout(self._layout)

    self._file_tree.installEventFilter(self);

    self.resize(800, 600)
    self.setWindowTitle('pyQtures')
    self.setCentralWidget(central_widget)
    self.show()

  def eventFilter(self, widget, event):
    if event.type() == QEvent.KeyPress:
      if event.key() == Qt.Key_Tab:
        self._toggle_path_suffix()
        return True
    return QMainWindow.eventFilter(self, widget, event)

  def _toggle_path_suffix(self):
    self._use_suffix = not self._use_suffix
    self._update_path()

  def _switch_to_fullscreen(self):
    self._splitter.widget(0).hide()
    self._layout.setMargin(0)
    self.showFullScreen()

  def _switch_to_normal(self):
    self._splitter.widget(0).show()
    self._layout.setMargin(4)
    self.showNormal()

  def keyPressEvent(self, key_event):  # Signal handler.
    key = key_event.key()
    if self.isFullScreen():
      self._full_screen_key_handler(key)
    else:
      self._normal_key_handler(key)

  def _full_screen_key_handler(self, key):
    if Qt.Key_Escape == key:
      self._switch_to_normal()
    elif Qt.Key_Return == key:
      self._switch_to_normal()
    elif Qt.Key_Up == key:
      self._go_to_sibling_image(-1)
    elif Qt.Key_Down == key:
      self._go_to_sibling_image(1)
    elif Qt.Key_Tab == key:
      self._toggle_path_suffix()

  def _go_to_sibling_image(self, offset):
    current = self._file_selection_model.currentIndex()
    nxt = current.sibling(current.row() + offset, current.column())
    if (nxt.parent() != current.parent()):
      return
    # TODO(eustas): Iterate through dirs?
    self._file_selection_model.setCurrentIndex(nxt, QItemSelectionModel.SelectCurrent)

  def _normal_key_handler(self, key):
    if Qt.Key_Escape == key:
      QCoreApplication.instance().quit()
    elif Qt.Key_Return == key:
      self._switch_to_fullscreen()

  def _on_current_file_changed(self, new_current):
    new_path = self._file_model.filePath(new_current)
    if not self._current_path == new_path:
        self._current_path = new_path
        self._update_path()

  def _update_path(self):
    if not self._use_suffix:
      self._viewer.set_path(self._current_path)
      return

    self._viewer.reset_path()
    if not self._current_path:
      return

    selected_file = QFileInfo(self._current_path)
    if not selected_file.exists():
      return

    selected_dir = selected_file.absoluteDir()
    file_name = selected_file.fileName()
    if not selected_dir.exists():
      return

    if not selected_dir.cd('converted'):
      return

    suffixed_path = selected_dir.absoluteFilePath(file_name)
    self._viewer.set_path(suffixed_path)

  def _on_tree_expanded_collapsed(self, unused_index):
    QTimer.singleShot(1, lambda: self._file_tree.resizeColumnToContents(0))
Exemplo n.º 25
0
class MainWindow(QMainWindow):
    def __init__(self, labeltool, parent=None):
        QMainWindow.__init__(self, parent)

        self.idletimer = QTimer()
        self.loader = None

        self.labeltool = labeltool
        self.setupGui()
        self.loadApplicationSettings()
        self.onAnnotationsLoaded()

    # Slots
    def onPluginLoaded(self, action):
        self.ui.menuPlugins.addAction(action)

    def onStatusMessage(self, message=''):
        self.statusBar().showMessage(message, 5000)

    def onModelDirtyChanged(self, dirty):
        postfix = "[+]" if dirty else ""
        if self.labeltool.getCurrentFilename() is not None:
            self.setWindowTitle("%s - %s %s" % \
                (APP_NAME, QFileInfo(self.labeltool.getCurrentFilename()).fileName(), postfix))
        else:
            self.setWindowTitle("%s - Unnamed %s" % (APP_NAME, postfix))

    def onMousePositionChanged(self, x, y):
        self.posinfo.setText("%d, %d" % (x, y))

    def startBackgroundLoading(self):
        self.stopBackgroundLoading(forced=True)
        self.loader = BackgroundLoader(self.labeltool.model(), self.statusBar(), self.sb_progress)
        self.idletimer.timeout.connect(self.loader.load)
        self.loader.finished.connect(self.stopBackgroundLoading)
        self.statusBar().addWidget(self.sb_progress)
        self.sb_progress.show()
        self.idletimer.start()

    def stopBackgroundLoading(self, forced=False):
        if not forced:
            self.statusBar().showMessage("Background loading finished", 5000)
        self.idletimer.stop()
        if self.loader is not None:
            self.idletimer.timeout.disconnect(self.loader.load)
            self.statusBar().removeWidget(self.sb_progress)
            self.loader = None

    def onAnnotationsLoaded(self):
        self.labeltool.model().dirtyChanged.connect(self.onModelDirtyChanged)
        self.onModelDirtyChanged(self.labeltool.model().dirty())
        self.treeview.setModel(self.labeltool.model())
        self.scene.setModel(self.labeltool.model())
        self.selectionmodel = QItemSelectionModel(self.labeltool.model())
        self.treeview.setSelectionModel(self.selectionmodel)
        self.treeview.selectionModel().currentChanged.connect(self.labeltool.setCurrentImage)
        self.property_editor.onModelChanged(self.labeltool.model())
        self.startBackgroundLoading()

    def onCurrentImageChanged(self):
        new_image = self.labeltool.currentImage()
        self.scene.setCurrentImage(new_image)
        self.onFitToWindowModeChanged()
        self.treeview.scrollTo(new_image.index())

        img = self.labeltool.getImage(new_image)

        if img == None:
            self.controls.setFilename("")
            self.selectionmodel.setCurrentIndex(new_image.index(), QItemSelectionModel.ClearAndSelect|QItemSelectionModel.Rows)
            return

        h = img.shape[0]
        w = img.shape[1]
        self.image_resolution.setText("%dx%d" % (w, h))

        # TODO: This info should be obtained from AnnotationModel or LabelTool
        if isinstance(new_image, FrameModelItem):
            self.controls.setFrameNumAndTimestamp(new_image.framenum(), new_image.timestamp())
        elif isinstance(new_image, ImageFileModelItem):
            self.controls.setFilename(os.path.basename(new_image['filename']))

        self.selectionmodel.setCurrentIndex(new_image.index(), QItemSelectionModel.ClearAndSelect|QItemSelectionModel.Rows)

    def onFitToWindowModeChanged(self):
        if self.options["Fit-to-window mode"].isChecked():
            self.view.fitInView()

    def onScaleChanged(self, scale):
        self.zoominfo.setText("%.2f%%" % (100 * scale, ))

    def initShortcuts(self, HOTKEYS):
        self.shortcuts = []

        for hotkey in HOTKEYS:
            assert len(hotkey) >= 2
            key = hotkey[0]
            fun = hotkey[1]
            desc = ""
            if len(hotkey) > 2:
                desc = hotkey[2]
            if type(fun) == str:
                fun = import_callable(fun)

            hk = QAction(desc, self)
            hk.setShortcut(QKeySequence(key))
            hk.setEnabled(True)
            if hasattr(fun, '__call__'):
                hk.triggered.connect(bind(fun, self.labeltool))
            else:
                hk.triggered.connect(compose_noargs([bind(f, self.labeltool) for f in fun]))
            self.ui.menuShortcuts.addAction(hk)
            self.shortcuts.append(hk)

    def initOptions(self):
        self.options = {}
        for o in ["Fit-to-window mode"]:
            action = QAction(o, self)
            action.setCheckable(True)
            self.ui.menuOptions.addAction(action)
            self.options[o] = action

    ###
    ### GUI/Application setup
    ###___________________________________________________________________________________________
    def setupGui(self):
        self.ui = uic.loadUi(os.path.join(GUIDIR, "labeltool.ui"), self)

        # get inserters and items from labels
        # FIXME for handling the new-style config correctly
        inserters = dict([(label['attributes']['class'], label['inserter']) 
                          for label in config.LABELS
                          if 'class' in label.get('attributes', {}) and 'inserter' in label])
        items = dict([(label['attributes']['class'], label['item']) 
                      for label in config.LABELS
                      if 'class' in label.get('attributes', {}) and 'item' in label])

        # Property Editor
        self.property_editor = PropertyEditor(config.LABELS)
        self.ui.dockProperties.setWidget(self.property_editor)

        # Scene
        self.scene = AnnotationScene(self.labeltool, items=items, inserters=inserters)
        self.property_editor.insertionModeStarted.connect(self.scene.onInsertionModeStarted)
        self.property_editor.insertionModeEnded.connect(self.scene.onInsertionModeEnded)

        # SceneView
        self.view = GraphicsView(self)
        self.view.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.view.setScene(self.scene)

        self.central_widget = QWidget()
        self.central_layout = QVBoxLayout()
        self.controls = ControlButtonWidget()
        self.controls.back_button.clicked.connect(self.labeltool.gotoPrevious)
        self.controls.forward_button.clicked.connect(self.labeltool.gotoNext)

        self.central_layout.addWidget(self.controls)
        self.central_layout.addWidget(self.view)
        self.central_widget.setLayout(self.central_layout)
        self.setCentralWidget(self.central_widget)

        self.initShortcuts(config.HOTKEYS)
        self.initOptions()

        self.treeview = AnnotationTreeView()
        self.treeview.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
        self.ui.dockAnnotations.setWidget(self.treeview)

        self.scene.selectionChanged.connect(self.scene.onSelectionChanged)
        self.treeview.selectedItemsChanged.connect(self.scene.onSelectionChangedInTreeView)

        self.posinfo = QLabel("-1, -1")
        self.posinfo.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.posinfo)
        self.scene.mousePositionChanged.connect(self.onMousePositionChanged)

        self.image_resolution = QLabel("[no image]")
        self.image_resolution.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.image_resolution)

        self.zoominfo = QLabel()
        self.zoominfo.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.zoominfo)
        self.view.scaleChanged.connect(self.onScaleChanged)
        self.onScaleChanged(self.view.getScale())

        self.sb_progress = QProgressBar()

        # View menu
        self.ui.menu_Views.addAction(self.ui.dockProperties.toggleViewAction())
        self.ui.menu_Views.addAction(self.ui.dockAnnotations.toggleViewAction())

        # Show the UI.  It is important that this comes *after* the above 
        # adding of custom widgets, especially the central widget.  Otherwise the
        # dock widgets would be far to large.
        self.ui.show()

        ## connect action signals
        self.connectActions()

    def connectActions(self):
        ## File menu
        self.ui.actionNew.    triggered.connect(self.fileNew)
        self.ui.actionOpen.   triggered.connect(self.fileOpen)
        self.ui.actionSave.   triggered.connect(self.fileSave)
        self.ui.actionSave_As.triggered.connect(self.fileSaveAs)
        self.ui.actionExit.   triggered.connect(self.close)

        ## View menu
        self.ui.actionLocked.toggled.connect(self.onViewsLockedChanged)

        ## Help menu
        self.ui.action_About.triggered.connect(self.about)

        ## Navigation
        self.ui.action_Add_Image.triggered.connect(self.addMediaFile)
        self.ui.actionNext.      triggered.connect(self.labeltool.gotoNext)
        self.ui.actionPrevious.  triggered.connect(self.labeltool.gotoPrevious)
        self.ui.actionZoom_In.   triggered.connect(functools.partial(self.view.setScaleRelative, 1.2))
        self.ui.actionZoom_Out.  triggered.connect(functools.partial(self.view.setScaleRelative, 1/1.2))

        ## Connections to LabelTool
        self.labeltool.pluginLoaded.       connect(self.onPluginLoaded)
        self.labeltool.statusMessage.      connect(self.onStatusMessage)
        self.labeltool.annotationsLoaded.  connect(self.onAnnotationsLoaded)
        self.labeltool.currentImageChanged.connect(self.onCurrentImageChanged)

        ## options menu
        self.options["Fit-to-window mode"].changed.connect(self.onFitToWindowModeChanged)

    def loadApplicationSettings(self):
        settings = QSettings()
        size   = settings.value("MainWindow/Size", QSize(800, 600))
        pos    = settings.value("MainWindow/Position", QPoint(10, 10))
        state  = settings.value("MainWindow/State")
        locked = settings.value("MainWindow/ViewsLocked", False)
        if isinstance(size,   QVariant): size  = size.toSize()
        if isinstance(pos,    QVariant): pos   = pos.toPoint()
        if isinstance(state,  QVariant): state = state.toByteArray()
        if isinstance(locked, QVariant): locked = locked.toBool()
        self.resize(size)
        self.move(pos)
        if state is not None:
                self.restoreState(state)
        self.ui.actionLocked.setChecked(bool(locked))

    def saveApplicationSettings(self):
        settings = QSettings()
        settings.setValue("MainWindow/Size",        self.size())
        settings.setValue("MainWindow/Position",    self.pos())
        settings.setValue("MainWindow/State",       self.saveState())
        settings.setValue("MainWindow/ViewsLocked", self.ui.actionLocked.isChecked())
        if self.labeltool.getCurrentFilename() is not None:
            filename = self.labeltool.getCurrentFilename()
        else:
            filename = None
        settings.setValue("LastFile", filename)

    def okToContinue(self):
        if self.labeltool.model().dirty():
            reply = QMessageBox.question(self,
                    "%s - Unsaved Changes" % (APP_NAME),
                    "Save unsaved changes?",
                    QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return False
            elif reply == QMessageBox.Yes:
                return self.fileSave()
        return True

    def fileNew(self):
        if self.okToContinue():
            self.labeltool.clearAnnotations()

    def fileOpen(self):
        if not self.okToContinue():
            return
        path = '.'
        filename = self.labeltool.getCurrentFilename()
        if (filename is not None) and (len(filename) > 0):
            path = QFileInfo(filename).path()

        format_str = ' '.join(self.labeltool.getAnnotationFilePatterns())
        fname = QFileDialog.getOpenFileName(self, 
                "%s - Load Annotations" % APP_NAME, path,
                "%s annotation files (%s)" % (APP_NAME, format_str))
        if len(str(fname)) > 0:
            self.labeltool.loadAnnotations(fname)

    def fileSave(self):
        filename = self.labeltool.getCurrentFilename()
        if filename is None:
            return self.fileSaveAs()
        return self.labeltool.saveAnnotations(filename)

    def fileSaveAs(self):
        fname = '.'  # self.annotations.filename() or '.'
        format_str = ' '.join(self.labeltool.getAnnotationFilePatterns())
        fname = QFileDialog.getSaveFileName(self,
                "%s - Save Annotations" % APP_NAME, fname,
                "%s annotation files (%s)" % (APP_NAME, format_str))

        if len(str(fname)) > 0:
            return self.labeltool.saveAnnotations(str(fname))
        return False

    def addMediaFile(self):
        path = '.'
        filename = self.labeltool.getCurrentFilename()
        if (filename is not None) and (len(filename) > 0):
            path = QFileInfo(filename).path()

        image_types = [ '*.jpg', '*.bmp', '*.png', '*.pgm', '*.ppm', '*.ppm', '*.tif', '*.gif' ]
        video_types = [ '*.mp4', '*.mpg', '*.mpeg', '*.avi', '*.mov', '*.vob' ]
        format_str = ' '.join(image_types + video_types)
        fnames = QFileDialog.getOpenFileNames(self, "%s - Add Media File" % APP_NAME, path, "Media files (%s)" % (format_str, ))

        item = None
        numFiles = len(fnames)
        progress_bar = QProgressDialog('Importing files...', 'Cancel import', 0, numFiles, self)
        for fname,c in zip(fnames, range(numFiles)):
            if len(str(fname)) == 0:
                continue

            fname = str(fname)

            if os.path.isabs(fname):
                fname = os.path.relpath(fname, str(path))

            for pattern in image_types:
                if fnmatch.fnmatch(fname, pattern):
                    item = self.labeltool.addImageFile(fname)
            
            progress_bar.setValue(c)

        if item is None:
            return self.labeltool.addVideoFile(fname)

        progress_bar.close()
        
        return item

    def onViewsLockedChanged(self, checked):
        features = QDockWidget.AllDockWidgetFeatures
        if checked:
            features = QDockWidget.NoDockWidgetFeatures 

        self.ui.dockProperties.setFeatures(features)
        self.ui.dockAnnotations.setFeatures(features)


    ###
    ### global event handling
    ###______________________________________________________________________________
    def closeEvent(self, event):
        if self.okToContinue():
            self.saveApplicationSettings()
        else:
            event.ignore()

    def about(self):
        QMessageBox.about(self, "About %s" % APP_NAME,
             """<b>%s</b> version %s
             <p>This labeling application for computer vision research
             was developed at the CVHCI research group at KIT.
             <p>For more details, visit our homepage: <a href="%s">%s</a>"""
              % (APP_NAME, __version__, ORGANIZATION_DOMAIN, ORGANIZATION_DOMAIN))
Exemplo n.º 26
0
class LayerStackModel(QAbstractListModel):
    canMoveSelectedUp = pyqtSignal("bool")
    canMoveSelectedDown = pyqtSignal("bool")
    canDeleteSelected = pyqtSignal("bool")

    orderChanged = pyqtSignal()
    layerAdded = pyqtSignal(Layer, int)  # is now in row
    layerRemoved = pyqtSignal(Layer, int)  # was in row
    stackCleared = pyqtSignal()

    def __init__(self, parent=None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.updateGUI)
        self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
        self._movingRows = False
        QTimer.singleShot(0, self.updateGUI)

        def _handleRemovedLayer(layer):
            # Layerstacks *own* the layers they hold, and thus are
            #  responsible for cleaning them up when they are removed:
            layer.clean_up()

        self.layerRemoved.connect(_handleRemovedLayer)

    ####
    ## High level API to manipulate the layerstack
    ###

    def __len__(self):
        return self.rowCount()

    def __repr__(self):
        return "<LayerStackModel: layerStack='%r'>" % (self._layerStack, )

    def __getitem__(self, i):
        return self._layerStack[i]

    def __iter__(self):
        return self._layerStack.__iter__()

    def layerIndex(self, layer):
        #note that the 'index' function already has a different implementation
        #from Qt side
        return self._layerStack.index(layer)

    def findMatchingIndex(self, func):
        """Call the given function with each layer and return the index of the first layer for which f is True."""
        for index, layer in enumerate(self._layerStack):
            if func(layer):
                return index
        raise ValueError("No matching layer in stack.")

    def append(self, data):
        self.insert(0, data)

    def clear(self):
        if len(self) > 0:
            self.removeRows(0, len(self))
            self.stackCleared.emit()

    def insert(self, index, data):
        """
        Insert a layer into this layer stack, which *takes ownership* of the layer.
        """
        assert isinstance(
            data, Layer), "Only Layers can be added to a LayerStackModel"
        self.insertRow(index)
        self.setData(self.index(index), data)
        if self.selectedRow() >= 0:
            self.selectionModel.select(self.index(self.selectedRow()),
                                       QItemSelectionModel.Deselect)
        self.selectionModel.select(self.index(index),
                                   QItemSelectionModel.Select)

        data.changed.connect(
            functools.partial(self._onLayerChanged, self.index(index)))
        index = self._layerStack.index(data)
        self.layerAdded.emit(data, index)

        self.updateGUI()

    def selectRow(self, row):
        already_selected_rows = self.selectionModel.selectedRows()
        if len(already_selected_rows) == 1 and row == already_selected_rows[0]:
            # Nothing to do if this row is already selected
            return
        self.selectionModel.clear()
        self.selectionModel.setCurrentIndex(self.index(row),
                                            QItemSelectionModel.SelectCurrent)

    @pyqtSignature("deleteSelected()")
    def deleteSelected(self):
        num_rows = len(self.selectionModel.selectedRows())
        assert num_rows == 1, "Can't delete selected row: {} layers are currently selected.".format(
            num_rows)
        row = self.selectionModel.selectedRows()[0]
        layer = self._layerStack[row.row()]
        assert not layer._cleaned_up, "This layer ({}) has already been cleaned up.  Shouldn't it already be removed from the layerstack?".format(
            layer.name)
        self.removeRow(row.row())
        if self.rowCount() > 0:
            self.selectionModel.select(self.index(0),
                                       QItemSelectionModel.Select)
        self.layerRemoved.emit(layer, row.row())
        self.updateGUI()

    @pyqtSignature("moveSelectedUp()")
    def moveSelectedUp(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = oldRow - 1
            self._moveToRow(oldRow, newRow)

    @pyqtSignature("moveSelectedDown()")
    def moveSelectedDown(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = oldRow + 1
            self._moveToRow(oldRow, newRow)

    @pyqtSignature("moveSelectedToTop()")
    def moveSelectedToTop(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = 0
            self._moveToRow(oldRow, newRow)

    @pyqtSignature("moveSelectedToBottom()")
    def moveSelectedToBottom(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = self.rowCount() - 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedToRow(self, newRow):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != newRow:
            oldRow = row.row()
            self._moveToRow(oldRow, newRow)

    def _moveToRow(self, oldRow, newRow):
        d = self._layerStack[oldRow]
        self.removeRow(oldRow)
        self.insertRow(newRow)
        self.setData(self.index(newRow), d)
        self.selectionModel.select(self.index(newRow),
                                   QItemSelectionModel.Select)
        self.orderChanged.emit()
        self.updateGUI()

    ####
    ## Low level API. To add, remove etc. layers use the high level API from above.
    ####

    def updateGUI(self):
        self.canMoveSelectedUp.emit(self.selectedRow() > 0)
        self.canMoveSelectedDown.emit(self.selectedRow() < self.rowCount() - 1)
        self.canDeleteSelected.emit(self.rowCount() > 0)
        self.wantsUpdate()

    def selectedRow(self):
        selected = self.selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=QModelIndex()):
        if not parent.isValid():
            return len(self._layerStack)
        return 0

    def insertRows(self, row, count, parent=QModelIndex()):
        '''Insert empty rows in the stack. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Always use the insert() or append() method.
        
        '''
        if parent.isValid():
            return False
        oldRowCount = self.rowCount()
        #for some reason, row can be negative!
        beginRow = max(0, row)
        endRow = min(beginRow + count - 1, len(self._layerStack))
        self.beginInsertRows(parent, beginRow, endRow)
        while (beginRow <= endRow):
            self._layerStack.insert(row, Layer(datasources=[]))
            beginRow += 1
        self.endInsertRows()
        assert self.rowCount(
        ) == oldRowCount + 1, "oldRowCount = %d, self.rowCount() = %d" % (
            oldRowCount, self.rowCount())
        return True

    def removeRows(self, row, count, parent=QModelIndex()):
        '''Remove rows from the stack. 
        
        DO NOT USE THIS METHOD TO REMOVE LAYERS!
        Use the deleteSelected() method instead.
        
        '''

        if parent.isValid():
            return False
        if row + count <= 0 or row >= len(self._layerStack):
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0, row)
        endRow = min(row + count - 1, len(self._layerStack) - 1)
        self.beginRemoveRows(parent, beginRow, endRow)
        while (beginRow <= endRow):
            del self._layerStack[row]
            beginRow += 1
        self.endRemoveRows()
        return True

    def flags(self, index):
        defaultFlags = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
        if index.isValid():
            return Qt.ItemIsDragEnabled | defaultFlags
        else:
            return Qt.ItemIsDropEnabled | defaultFlags

    def supportedDropActions(self):
        return Qt.MoveAction

    def data(self, index, role=Qt.DisplayRole):
        if not index.isValid():
            return None
        if index.row() > len(self._layerStack):
            return None

        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._layerStack[index.row()]
        elif role == Qt.ToolTipRole:
            return self._layerStack[index.row()].toolTip()
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        '''Replace one layer with another. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Use deleteSelected() followed by insert() or append().
        
        '''
        if role == Qt.EditRole:
            layer = value
            if not isinstance(value, Layer):
                layer = value.toPyObject()
            self._layerStack[index.row()] = layer
            self.dataChanged.emit(index, index)
            return True
        elif role == Qt.ToolTipRole:
            self._layerStack[index.row()].setToolTip()
            return True
        return False

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return "Column %r" % section
        else:
            return "Row %r" % section

    def wantsUpdate(self):
        self.layoutChanged.emit()

    def _onLayerChanged(self, idx):
        self.dataChanged.emit(idx, idx)
        self.updateGUI()

    def _onSelectionChanged(self, selected, deselected):
        for idx in deselected.indexes():
            self[idx.row()].setActive(False)
        for idx in selected.indexes():
            self[idx.row()].setActive(True)
Exemplo n.º 27
0
class imdbSearchDialog(QtGui.QDialog): 
    def __init__(self, parent):
        QtGui.QDialog.__init__(self)
        self.ui = Ui_IMDBSearchDialog()
        self.ui.setupUi(self)
        self._main  = parent
        
        QObject.connect(self.ui.searchMovieButton, SIGNAL("clicked(bool)"), self.onSearchMovieButton)
        QObject.connect(self.ui.movieInfoButton, SIGNAL("clicked(bool)"), self.onMovieInfoButton)
        QObject.connect(self.ui.okButton, SIGNAL("clicked(bool)"), self.onOkButton)
        QObject.connect(self.ui.cancelButton, SIGNAL("clicked(bool)"), self.onCancelButton)
        
        header = self.ui.searchResultsView.horizontalHeader()
        header.setResizeMode(QtGui.QHeaderView.Stretch)
        header.hide()
        self.ui.searchResultsView.verticalHeader().hide()
        
        self.imdbModel = ImdbListModel(self)
        self.ui.searchResultsView.setModel(self.imdbModel)
        self.imdbModel._main = self #FIXME: This connection should be cleaner.
        self.imdbSelectionModel = QItemSelectionModel(self.imdbModel)
        self.ui.searchResultsView.setSelectionModel(self.imdbSelectionModel)
        QObject.connect(self.imdbSelectionModel, SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), self.onIMDBChangeSelection)
        QObject.connect(self.ui.searchResultsView, SIGNAL("activated(QModelIndex)"), self.onOkButton)

    def onSearchMovieButton(self):
        if not self.ui.movieSearch.text():
            QMessageBox.about(self,_("Error"),_("Please fill out the search title"))
        else:
            self.setCursor(Qt.WaitCursor)
            text = self.ui.movieSearch.text()
            try:
                results = self._main.OSDBServer.SearchMoviesOnIMDB(str(text.toUtf8()))
                if not results or not len(results) or not results[0].has_key("id"): #In case of empty results 
                    results = []
            except:
                QMessageBox.about(self,_("Error"),_("Error contacting the server. Please try again later"))
                results = []
            
            self.imdbModel.emit(SIGNAL("layoutAboutToBeChanged()"))
            self.imdbModel.setImdbResults(results)
            QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
            self.imdbModel.emit(SIGNAL("layoutChanged()"))
            self.ui.searchResultsView.resizeRowsToContents()
            self.setCursor(Qt.ArrowCursor)
            
    def updateButtonsIMDB(self):
        self.ui.searchResultsView.resizeRowsToContents()
        selected = self.imdbSelectionModel.selection()
        if selected.count():
            self.imdbModel.rowSelected = selected.last().bottomRight().row()
            self.ui.movieInfoButton.setEnabled(True)
            self.ui.okButton.setEnabled(True)
        else:
            self.imdbModel.rowSelected = None
            self.ui.movieInfoButton.setEnabled(False)
            self.ui.okButton.setEnabled(False)
            
    def onIMDBChangeSelection(self, selected, unselected):
        self.updateButtonsIMDB()
        
    def onMovieInfoButton(self):
        if self.imdbModel.rowSelected == None:
            QMessageBox.about(self,_("Error"),_("Please search and select a movie from the list"))
        else: 
            imdbID = self.imdbModel.getSelectedImdb()["id"]
            webbrowser.open( "http://www.imdb.com/title/tt%s"% imdbID, new=2, autoraise=1)
    def onOkButton(self):
        if self.imdbModel.rowSelected == None:
            QMessageBox.about(self,_("Error"),_("Please search and select a movie from the list"))
        else:
            selection = self.imdbModel.getSelectedImdb()
            self._main.emit(SIGNAL('imdbDetected(QString,QString,QString)'),selection["id"], selection["title"], "search")
            self.accept()
    def onCancelButton(self):
        self.reject()
Exemplo n.º 28
0
class LabelListModel(QAbstractTableModel):
    orderChanged = pyqtSignal()
    labelSelected = pyqtSignal(int)

    def __init__(self, labels=[], parent=None):
        QAbstractTableModel.__init__(self, parent)
        self._labels = labels
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):
            if selected:
                self.labelSelected.emit(selected[0].indexes()[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}

    def __len__(self):
        return len(self._labels)

    def __getitem__(self, i):
        return self._labels[i]

    def selectedRow(self):
        selected = self._selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=None):
        return len(self._labels)

    def columnCount(self, parent):
        return 3

    def _getToolTipSuffix(self, row):
        """
        Get the middle column tooltip suffix
        """
        suffix = "; Click to select"
        if row in self._toolTipSuffixes:
            suffix = self._toolTipSuffixes[row]
        return suffix

    def _setToolTipSuffix(self, row, text):
        """
        Set the middle column tooltip suffix
        """
        self._toolTipSuffixes[row] = text
        index = self.createIndex(row, 1)
        self.dataChanged.emit(index, index)

    class EntryToolTipAdapter(object):
        """
        This class can be used to make each row look like a separate widget with its own tooltip.
        In this case, the "tooltip" is the suffix appended to the tooltip of the middle column.
        """
        def __init__(self, table, row):
            self._row = row
            self._table = table

        def toolTip(self):
            return self._table._getToolTipSuffix(self._row)

        def setToolTip(self, text):
            self._table._setToolTipSuffix(self._row, text)

    def data(self, index, role):
        if role == Qt.EditRole and index.column() == 0:
            return self._labels[index.row()].color
        if role == Qt.EditRole and index.column() == 1:
            return self._labels[index.row()].name

        if role == Qt.ToolTipRole and index.column() == 0:
            return "Hex code : " + self._labels[
                index.row()].color.name() + "\n DoubleClick to change"
        if role == Qt.ToolTipRole and index.column() == 1:
            suffix = self._getToolTipSuffix(index.row())
            return self._labels[
                index.row()].name + "\n DoubleClick to rename" + suffix
        if role == Qt.ToolTipRole and index.column() == 2:
            return "Delete " + self._labels[index.row()].name

        if role == Qt.DecorationRole and index.column() == 0:
            row = index.row()
            value = self._labels[row]
            pixmap = QPixmap(26, 26)
            pixmap.fill(value.color)
            icon = QIcon(pixmap)
            return icon

        if role == Qt.DecorationRole and index.column() == 2:
            row = index.row()
            pixmap = QPixmap(26, 26)
            pixmap.fill(Qt.transparent)
            painter = QPainter()
            painter.begin(pixmap)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setBrush(QColor("red"))
            painter.drawEllipse(1, 1, 24, 24)
            pen = QPen(QColor("black"))
            pen.setWidth(2)
            painter.setPen(pen)
            painter.drawLine(8, 8, 18, 18)
            painter.drawLine(18, 8, 8, 18)

            painter.end()
            icon = QIcon(pixmap)
            return icon

        if role == Qt.DisplayRole and index.column() == 1:
            row = index.row()
            value = self._labels[row]
            return value.name

    def flags(self, index):
        if index.column() == 0:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif index.column() == 1:
            return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif index.column() == 2:
            if self._allowRemove:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                return Qt.NoItemFlags

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole and index.column() == 0:
            row = index.row()
            color = QColor(value)
            if color.isValid():
                self._labels[row].color = color
                self.dataChanged.emit(index, index)
                return True

        if role == Qt.EditRole and index.column() == 1:
            row = index.row()
            name = value
            self._labels[row].name = str(name.toString())
            self.dataChanged.emit(index, index)
            return True

        return False

    def insertRow(self, position, object, parent=QModelIndex()):
        self.beginInsertRows(parent, position, position)
        self._labels.insert(position, object)
        self.endInsertRows()
        return True

    def removeRow(self, position, parent=QModelIndex()):
        self.beginRemoveRows(parent, position, position)
        value = self._labels[position]
        logger.debug("removing row: " + str(value))
        self._labels.remove(value)
        self.endRemoveRows()
        return True

    def allowRemove(self, check):
        #Allow removing of rows. Needed to be able to disallow it
        #in interactive mode
        self._allowRemove = check
        self.dataChanged.emit(self.createIndex(0, 2),
                              self.createIndex(self.rowCount(), 2))

    def select(self, row):
        self._selectionModel.clear()
        self._selectionModel.select(self.index(row, 0),
                                    QItemSelectionModel.Select)
        self._selectionModel.select(self.index(row, 1),
                                    QItemSelectionModel.Select)
Exemplo n.º 29
0
class ListModel(QAbstractTableModel):
    orderChanged = pyqtSignal()
    elementSelected = pyqtSignal(int)


    class ColumnID():
        '''
        Define how many column the model holds and their type

        '''
        ncols=2
        Name=0
        Delete=1

    def __init__(self, elements=None, parent=None):
        '''
        Common interface for the labelListModel and the boxListModel
        see concrete implementations for details

        :param elements:
        :param parent:
        '''
        QAbstractTableModel.__init__(self, parent)

        if elements is None:
            elements = []
        self._elements = list(elements)
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):


            if selected:
                ind = selected[0].indexes()
                if len(ind)>0:
                    self.elementSelected.emit(ind[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}

        self.unremovable_rows=[] #rows in this list cannot be removed from the gui,
                                 # to add to this list call self.makeRowPermanent(int)
                                 # to remove make the self.makeRowRemovable(int)
    def makeRowPermanent(self,rowindex):
        """
        The rowindex cannot be removed from gui
        to remove this index use self.makeRowRemovable
        """

        self.unremovable_rows.append(rowindex)

    def makeRowRemovable(self,rowindex):
        self.unremovable_rows.pop(rowindex)

    def __len__(self):
        return len(self._elements)

    def __getitem__(self, i):
        return self._elements[i]

    def selectedRow(self):
        selected = self._selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=None):
        return len(self._elements)

    def columnCount(self, parent):
        return self.ColumnID.ncols

    def _getToolTipSuffix(self, row):
        """
        Get the middle column tooltip suffix
        """
        suffix = "; Click to select"
        if row in self._toolTipSuffixes:
            suffix = self._toolTipSuffixes[row]
        return suffix

    def _setToolTipSuffix(self, row, text):
        """
        Set the middle column tooltip suffix
        """
        self._toolTipSuffixes[row] = text
        index = self.createIndex(row, 1)
        self.dataChanged.emit(index, index)

    class EntryToolTipAdapter(object):
        """This class can be used to make each row look like a
        separate widget with its own tooltip.

        In this case, the "tooltip" is the suffix appended to the
        tooltip of the middle column.

        """
        def __init__(self, table, row):
            self._row = row
            self._table = table
        def toolTip(self):
            return self._table._getToolTipSuffix(self._row)
        def setToolTip(self, text):
            self._table._setToolTipSuffix(self._row, text)



    def insertRow(self, position, object, parent=QModelIndex()):
        self.beginInsertRows(parent, position, position)
        object.changed.connect(self.modelReset)
        self._elements.insert(position, object)
        self.endInsertRows()
        return True

    def removeRow(self, position, parent=QModelIndex()):
        if position in self.unremovable_rows:
            return False

        self.beginRemoveRows(parent, position, position)
        value = self._elements[position]
        logger.debug("removing row: " + str(value))
        self._elements.remove(value)
        self.endRemoveRows()
        return True

    def allowRemove(self, check):
        #Allow removing of rows. Needed to be able to disallow it
        #in interactive mode
        self._allowRemove = check
        self.dataChanged.emit(self.createIndex(0, self.ColumnID.Delete),
                              self.createIndex(self.rowCount(), self.ColumnID.Delete))
    def data(self, index, role):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param index:
        :param role:
        '''

        if role == Qt.EditRole and index.column() == self.ColumnID.Name:
            name = self._elements[index.row()].name
            return decode_to_qstring(name, 'utf-8')

        elif role == Qt.ToolTipRole and index.column() == self.ColumnID.Delete:
            s = "Delete {}".format(self._elements[index.row()].name)
            return decode_to_qstring(s, 'utf-8')

        elif role == Qt.ToolTipRole and index.column() == self.ColumnID.Name:
            suffix = self._getToolTipSuffix(index.row())
            s = "{}\nDouble click to rename {}".format(
                self._elements[index.row()].name, suffix)
            return decode_to_qstring(s, 'utf-8')
        elif role == Qt.DisplayRole and index.column() == self.ColumnID.Name:
            name = self._elements[index.row()].name
            return decode_to_qstring(name, 'utf-8')

        if role == Qt.DecorationRole and index.column() == self.ColumnID.Delete:
            if index.row() in self.unremovable_rows: return

            row = index.row()
            pixmap = QPixmap(_NPIXELS, _NPIXELS)
            pixmap.fill(Qt.transparent)
            painter = QPainter()
            painter.begin(pixmap)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setBrush(QColor("red"))
            painter.drawEllipse(1, 1, _NPIXELS - 2, _NPIXELS - 2)
            pen = QPen(QColor("black"))
            pen.setWidth(2)
            painter.setPen(pen)

            x = _XSTART
            y = _NPIXELS - x
            painter.drawLine(x, x, y, y)
            painter.drawLine(y, x, x, y)

            painter.end()
            icon = QIcon(pixmap)
            return icon

    def flags(self, index):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param index:
        '''
        if index.column() == self.ColumnID.Delete:
            if self._allowRemove:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                return Qt.NoItemFlags
        elif  index.column() == self.ColumnID.Name:
            return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def setData(self, index, value, role=Qt.EditRole):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param index:
        '''
        if role == Qt.EditRole  and index.column() == self.ColumnID.Name:
            row = index.row()
            # value is a user provided QVariant, possibly with unicode
            # characters in it. internally, we keep a str
            self._elements[row].name = encode_from_qstring(value.toString(), 'utf-8')
            self.dataChanged.emit(index, index)
            return True

        return False

    def select(self, row):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param row
        '''
        self._selectionModel.clear()
        self._selectionModel.select(self.index(row, self.ColumnID.Name),
                                    QItemSelectionModel.Select)

    def clearSelectionModel(self):
        self._selectionModel.clear()
Exemplo n.º 30
0
class Games(QDialog):
    """a dialog for selecting a game"""
    def __init__(self, parent=None):
        super(Games, self).__init__(parent)
        self.selectedGame = None
        self.onlyPending = True
        self.setWindowTitle(m18nc('kajongg', 'Games') + ' - Kajongg')
        self.setObjectName('Games')
        self.resize(700, 400)
        self.model = GamesModel(self)
        if Debug.modelTest:
            self.modelTest = ModelTest(self.model, self)

        self.view = MJTableView(self)
        self.view.setModel(self.model)
        self.selection = QItemSelectionModel(self.model, self.view)
        self.view.setSelectionModel(self.selection)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.view.setSelectionMode(QAbstractItemView.SingleSelection)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.newButton = self.buttonBox.addButton(
            m18nc('start a new game', "&New"), QDialogButtonBox.ActionRole)
        self.newButton.setIcon(KIcon("document-new"))
        self.newButton.clicked.connect(self.accept)
        self.loadButton = self.buttonBox.addButton(m18n("&Load"),
                                                   QDialogButtonBox.AcceptRole)
        self.loadButton.clicked.connect(self.loadGame)
        self.loadButton.setIcon(KIcon("document-open"))
        self.deleteButton = self.buttonBox.addButton(
            m18n("&Delete"), QDialogButtonBox.ActionRole)
        self.deleteButton.setIcon(KIcon("edit-delete"))
        self.deleteButton.clicked.connect(self.delete)

        chkPending = QCheckBox(m18n("Show only pending games"), self)
        chkPending.setChecked(True)
        cmdLayout = QHBoxLayout()
        cmdLayout.addWidget(chkPending)
        cmdLayout.addWidget(self.buttonBox)

        layout = QVBoxLayout()
        layout.addWidget(self.view)
        layout.addLayout(cmdLayout)
        self.setLayout(layout)
        StateSaver(self)

        self.selection.selectionChanged.connect(self.selectionChanged)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.view.doubleClicked.connect(self.loadGame)
        chkPending.stateChanged.connect(self.pendingOrNot)

    def showEvent(self, dummyEvent):
        """only now get the data set. Not doing this in__init__ would eventually
        make it easier to subclass from some generic TableEditor class"""
        self.setQuery()
        self.view.initView()
        self.selectionChanged()

    def keyPressEvent(self, event):
        """use insert/delete keys for insert/delete"""
        key = event.key()
        if key == Qt.Key_Insert:
            self.newEntry()
            return
        if key == Qt.Key_Delete:
            self.delete()
            event.ignore()
            return
        QDialog.keyPressEvent(self, event)

    def selectionChanged(self):
        """update button states according to selection"""
        selectedRows = len(self.selection.selectedRows())
        self.loadButton.setEnabled(selectedRows == 1)
        self.deleteButton.setEnabled(selectedRows >= 1)

    def setQuery(self):
        """define the query depending on self.OnlyPending"""
        query = "select g.id, g.starttime, " \
            "p0.name||'///'||p1.name||'///'||p2.name||'///'||p3.name " \
            "from game g, player p0," \
            "player p1, player p2, player p3 " \
            "where seed is null" \
            " and p0.id=g.p0 and p1.id=g.p1 " \
            " and p2.id=g.p2 and p3.id=g.p3 " \
            "%s" \
            "and exists(select 1 from score where game=g.id)" % \
            ("and g.endtime is null " if self.onlyPending else "")
        self.model.setQuery(query, DBHandle.default)
        self.model.setHeaderData(1, Qt.Horizontal, QVariant(m18n("Started")))
        self.model.setHeaderData(2, Qt.Horizontal, QVariant(m18n("Players")))
        self.view.hideColumn(0)

    def __idxForGame(self, game):
        """returns the model index for game"""
        for row in range(self.model.rowCount()):
            if self.model.record(row).field(0).value().toInt()[0] == game:
                return self.model.index(row, 0)
        return self.model.index(0, 0)

    def pendingOrNot(self, chosen):
        """do we want to see all games or only pending games?"""
        if self.onlyPending != chosen:
            self.onlyPending = chosen
            idx = self.view.currentIndex()
            selectedGame = self.model.record(idx.row()).value(0).toInt()[0]
            self.setQuery()
            idx = self.__idxForGame(selectedGame)
            self.view.selectRow(idx.row())
        self.view.setFocus()

    def loadGame(self):
        """load a game"""
        selnum = len(self.selection.selectedRows())
        if selnum != 1:
            # should never happen
            logException('loadGame: %d rows selected' % selnum)
        idx = self.view.currentIndex()
        self.selectedGame = self.model.record(idx.row()).value(0).toInt()[0]
        self.buttonBox.accepted.emit()

    def delete(self):
        """delete a game"""
        def answered(result, games):
            """question answered, result is True or False"""
            if result:
                cmdList = []
                for game in games:
                    cmdList.append("DELETE FROM score WHERE game = %d" % game)
                    cmdList.append("DELETE FROM game WHERE id = %d" % game)
                Query(cmdList)
                self.setQuery()  # just reload entire table

        deleteGames = list(x.data().toInt()[0]
                           for x in self.view.selectionModel().selectedRows(0))
        if len(deleteGames) == 0:
            # should never happen
            logException('delete: 0 rows selected')
        WarningYesNo(
            m18n("Do you really want to delete <numid>%1</numid> games?<br>" \
            "This will be final, you cannot cancel it with the cancel button",
            len(deleteGames))).addCallback(answered, deleteGames)
Exemplo n.º 31
0
class MainWindow(QMainWindow, Ui_MainWindow):
    '''
    Gestione Clienti v.0.2.0
    by TIME di Stefano Zamprogno
    @2009
    '''
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setupUi(self)

        self.setupMenu()
        self.restoreWinSettings()

        self.filename = None
        self.filtered = False
        self.db = QSqlDatabase.addDatabase("QSQLITE")

        self.loadInitialFile()
        self.setupUiSignals()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Down:
            self.addCliRecord()
        elif event.key() == Qt.Key_Escape:
            self.cModel.revertAll()
            self.cModel.select()
        else:
            QMainWindow.keyPressEvent(self, event)

    def setupMenu(self):
        # AboutBox
        self.connect(self.action_About, SIGNAL("triggered()"),
                    self.showAboutBox)
        # FileNew
        self.connect(self.action_New_File, SIGNAL("triggered()"),
                    self.newFile)

        # FileLoad
        self.connect(self.action_Load_File, SIGNAL("triggered()"),
                    self.openFile)


    def showAboutBox(self):
        dlg = aboutcli.AboutBox(self)
        dlg.exec_()

    def creaStrutturaDB(self):
        query = QSqlQuery()
        if not ("clienti" in self.db.tables()):
            if not query.exec_("""CREATE TABLE clienti (
                                id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
                                ragsoc VARCHAR(200) NOT NULL,
                                indirizzo VARCHAR(200) NOT NULL,
                                piva VARCHAR(15),
                                cf VARCHAR(15),
                                tel VARCHAR(30),
                                fax VARCHAR(30),
                                cell VARCHAR(30),
                                email VARCHAR(50),
                                note VARCHAR(100))"""):
                QMessageBox.warning(self, "Gestione Clienti",
                                QString("Creazione tabella clienti fallita!"))
                return False
            QMessageBox.information(self, "Gestione Clienti",
                                QString("Database Creato!"))
        return True

    def loadFile(self, fname=None):
        if fname is None:
            return
        if self.db.isOpen():
            self.db.close()
        self.db.setDatabaseName(QString(fname))
        if not self.db.open():
            QMessageBox.warning(self, "Gestione Clienti",
                                QString("Database Error: %1")
                                .arg(db.lastError().text()))
        else:
            if not self.creaStrutturaDB():
                return
            self.filename = unicode(fname)
            self.setWindowTitle("Gestione Clienti - %s" % self.filename)
            self.setupModels()
            self.setupTables()
            self.restoreTablesSettings()


    def loadInitialFile(self):
        settings = QSettings()
        fname = unicode(settings.value("Settings/lastFile").toString())
        if fname and QFile.exists(fname):
            self.loadFile(fname)


    def openFile(self):
        dir = os.path.dirname(self.filename) \
                if self.filename is not None else "."
        fname = QFileDialog.getOpenFileName(self,
                    "Gestione Clienti - Scegli database",
                    dir, "*.db")
        if fname:
            self.loadFile(fname)


    def newFile(self):
        dir = os.path.dirname(self.filename) \
                if self.filename is not None else "."
        fname = QFileDialog.getSaveFileName(self,
                    "Gestione DDT - Scegli database",
                    dir, "*.db")
        if fname:
            self.loadFile(fname)

    def restoreWinSettings(self):
        settings = QSettings()
        self.restoreGeometry(
                settings.value("MainWindow/Geometry").toByteArray())

    def restoreTablesSettings(self):
        settings = QSettings(self)
        # per la tablelview
        for column in range(1, self.cModel.columnCount()-1):
            width = settings.value("Settings/cTableView/%s" % column,
                                    QVariant(60)).toInt()[0]
            self.cTableView.setColumnWidth(column,
                                        width if width > 0 else 60)

    def closeEvent(self, event):
        settings = QSettings()
        settings.setValue("MainWindow/Geometry", QVariant(
                          self.saveGeometry()))
        if self.filename is not None:
            settings.setValue("Settings/lastFile", QVariant(self.filename))
        if self.db.isOpen():
            # salva larghezza colonne tabella
            for column in range(1, self.cModel.columnCount()-1):
                width = self.cTableView.columnWidth(column)
                if width:
                    settings.setValue("Settings/cTableView/%s" % column,
                                        QVariant(width))
            self.db.close()
            del self.db

    def setupModels(self):
        """
            Initialize all the application models
        """
        # setup clientiModel
        self.cModel = QSqlTableModel(self)
        self.cModel.setTable(QString("clienti"))
        self.cModel.setHeaderData(CID, Qt.Horizontal, QVariant("ID"))
        self.cModel.setHeaderData(CRAGSOC, Qt.Horizontal, QVariant("RagSoc"))
        self.cModel.setHeaderData(CIND, Qt.Horizontal, QVariant("Indirizzo"))
        self.cModel.setHeaderData(CPIVA, Qt.Horizontal, QVariant("PIva"))
        self.cModel.setHeaderData(CCF, Qt.Horizontal, QVariant("CF"))
        self.cModel.setHeaderData(CTEL, Qt.Horizontal, QVariant("Tel"))
        self.cModel.setHeaderData(CFAX, Qt.Horizontal, QVariant("Fax"))
        self.cModel.setHeaderData(CCELL, Qt.Horizontal, QVariant("Cell"))
        self.cModel.setHeaderData(CEMAIL, Qt.Horizontal, QVariant("Email"))
        self.cModel.setHeaderData(CNOTE, Qt.Horizontal, QVariant("Note"))
        self.cModel.select()

    def setupTables(self):
        """
            Initialize all the application tablesview
        """
        self.cTableView.setModel(self.cModel)
        self.cTableView.setItemDelegate(MyQSqlRelationalDelegate(self))
        self.cTableView.setColumnHidden(CID, True)
        self.cTableView.setWordWrap(True)
        self.cTableView.resizeRowsToContents()
        self.cTableView.setAlternatingRowColors(True)
        self.cItmSelModel = QItemSelectionModel(self.cModel)
        self.cTableView.setSelectionModel(self.cItmSelModel)
        self.cTableView.setSelectionBehavior(QTableView.SelectRows)
        self.cTableView.setSortingEnabled(True)

    def updateFilter(self):
        self.cModel.select()
        self.cTableView.setColumnHidden(CID, True)

    def applyFilter(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        filter = (  "ragsoc LIKE '%s' OR "
                    "indirizzo LIKE '%s' OR "
                    "note LIKE '%s'" %
                    ((self.filterLineEdit.text(),)*3))
        self.cModel.setFilter(filter)
        self.filtered = True
        self.updateFilter()

    def resetFilter(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        self.filtered = False
        self.filterLineEdit.setText("")
        self.cModel.setFilter("")
        self.updateFilter()

    def addCliRecord(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        customerIndex = self.cTableView.currentIndex()
        if self.filtered:
            self.resetFilter()
        self.cModel.submitAll()
        self.cModel.select()
        row = self.cModel.rowCount()
        self.cModel.insertRow(row)
        self.editindex = self.cModel.index(row, CRAGSOC)
        self.cTableView.setCurrentIndex(self.editindex)
        self.cTableView.edit(self.editindex)

    def delCliRecord(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        selrows = self.cItmSelModel.selectedRows()
        if not selrows:
            self.statusbar.showMessage(
                "No selected customers to delete...",
                5000)
            return
        if(QMessageBox.question(self, "Delete Customers",
                "Do you want to delete: {0} customer(s)?".format(len(selrows)),
                QMessageBox.Yes|QMessageBox.No) ==
                QMessageBox.No):
            return
        QSqlDatabase.database().transaction()
        query = QSqlQuery()
        query.prepare("DELETE FROM clienti WHERE id = :val")
        for i in selrows:
            if i.isValid():
                query.bindValue(":val", QVariant(i.data().toInt()[0]))
                query.exec_()
        QSqlDatabase.database().commit()
        self.cModel.select()

    def setupUiSignals(self):
        self.connect(self.addPushButton, SIGNAL("clicked()"),
                    self.addCliRecord)
        self.connect(self.delPushButton, SIGNAL("clicked()"),
                    self.delCliRecord)
        self.connect(self.filterPushButton, SIGNAL("clicked()"),
                    self.applyFilter)
        self.connect(self.resetPushButton, SIGNAL("clicked()"),
                    self.resetFilter)
        self.connect(self.filterLineEdit, SIGNAL("returnPressed()"),
                    self.applyFilter)
Exemplo n.º 32
0
class LayerStackModel(QAbstractListModel):
    canMoveSelectedUp = pyqtSignal("bool")
    canMoveSelectedDown = pyqtSignal("bool")
    canDeleteSelected = pyqtSignal("bool")
    
    orderChanged = pyqtSignal()
    layerAdded = pyqtSignal( Layer, int ) # is now in row
    layerRemoved = pyqtSignal( Layer, int ) # was in row
    stackCleared = pyqtSignal()
        
    def __init__(self, parent = None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.updateGUI)
        self.selectionModel.selectionChanged.connect(self._onSelectionChanged)
        self._movingRows = False
        QTimer.singleShot(0, self.updateGUI)
        
        def _handleRemovedLayer(layer):
            # Layerstacks *own* the layers they hold, and thus are 
            #  responsible for cleaning them up when they are removed:
            layer.clean_up()
        self.layerRemoved.connect( _handleRemovedLayer )

    ####
    ## High level API to manipulate the layerstack
    ###
    
    def __len__(self):
        return self.rowCount()
        
    def __repr__(self):
        return "<LayerStackModel: layerStack='%r'>" % (self._layerStack,)  
    
    def __getitem__(self, i):
        return self._layerStack[i]
    
    def __iter__(self):
        return self._layerStack.__iter__()
    
    def layerIndex(self, layer):
        #note that the 'index' function already has a different implementation
        #from Qt side
        return self._layerStack.index(layer)

    def findMatchingIndex(self, func):
        """Call the given function with each layer and return the index of the first layer for which f is True."""
        for index, layer in enumerate(self._layerStack):
            if func(layer):
                return index
        raise ValueError("No matching layer in stack.")

    def append(self, data):
        self.insert(0, data)
   
    def clear(self):
        if len(self) > 0:
            self.removeRows(0,len(self))
            self.stackCleared.emit()

    def insert(self, index, data):
        """
        Insert a layer into this layer stack, which *takes ownership* of the layer.
        """
        assert isinstance(data, Layer), "Only Layers can be added to a LayerStackModel"
        self.insertRow(index)
        self.setData(self.index(index), data)
        if self.selectedRow() >= 0:
            self.selectionModel.select(self.index(self.selectedRow()), QItemSelectionModel.Deselect)
        self.selectionModel.select(self.index(index), QItemSelectionModel.Select)
        
        data.changed.connect(functools.partial(self._onLayerChanged, self.index(index)))
        index = self._layerStack.index(data)
        self.layerAdded.emit(data, index)

        self.updateGUI()

    def selectRow( self, row ):
        self.selectionModel.setCurrentIndex( self.index(row), QItemSelectionModel.SelectCurrent)

    @pyqtSignature("deleteSelected()")
    def deleteSelected(self):
        num_rows = len(self.selectionModel.selectedRows())
        assert num_rows == 1, "Can't delete selected row: {} layers are currently selected.".format( num_rows )
        row = self.selectionModel.selectedRows()[0]
        layer = self._layerStack[row.row()]
        assert not layer._cleaned_up, "This layer ({}) has already been cleaned up.  Shouldn't it already be removed from the layerstack?".format( layer.name )
        self.removeRow(row.row())
        if self.rowCount() > 0:
            self.selectionModel.select(self.index(0), QItemSelectionModel.Select)
        self.layerRemoved.emit( layer, row.row() )
        self.updateGUI()
        
    @pyqtSignature("moveSelectedUp()")
    def moveSelectedUp(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = oldRow - 1
            self._moveToRow(oldRow, newRow)
    

    @pyqtSignature("moveSelectedDown()")
    def moveSelectedDown(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = oldRow + 1
            self._moveToRow(oldRow, newRow)
            
    @pyqtSignature("moveSelectedToTop()")
    def moveSelectedToTop(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = 0
            self._moveToRow(oldRow, newRow)
    
    @pyqtSignature("moveSelectedToBottom()")
    def moveSelectedToBottom(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = self.rowCount() - 1
            self._moveToRow(oldRow, newRow)

    def moveSelectedToRow(self, newRow):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != newRow:
            oldRow = row.row()
            self._moveToRow(oldRow, newRow)

    def _moveToRow(self, oldRow, newRow):
        d = self._layerStack[oldRow]
        self.removeRow(oldRow)
        self.insertRow(newRow)
        self.setData(self.index(newRow), d)
        self.selectionModel.select(self.index(newRow), QItemSelectionModel.Select)
        self.orderChanged.emit()
        self.updateGUI()
    ####
    ## Low level API. To add, remove etc. layers use the high level API from above.
    ####
 
    def updateGUI(self):
        self.canMoveSelectedUp.emit(self.selectedRow()>0)
        self.canMoveSelectedDown.emit(self.selectedRow()<self.rowCount()-1)
        self.canDeleteSelected.emit(self.rowCount() > 0)
        self.wantsUpdate()
        
    def selectedRow(self):
        selected = self.selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1
    
    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()
    
    def rowCount(self, parent = QModelIndex()):
        if not parent.isValid():
            return len(self._layerStack)
        return 0
    
    def insertRows(self, row, count, parent = QModelIndex()):
        '''Insert empty rows in the stack. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Always use the insert() or append() method.
        
        '''
        if parent.isValid():
            return False
        oldRowCount = self.rowCount()
        #for some reason, row can be negative!
        beginRow = max(0,row)
        endRow   = min(beginRow+count-1, len(self._layerStack))
        self.beginInsertRows(parent, beginRow, endRow) 
        while(beginRow <= endRow):
            self._layerStack.insert(row, Layer(datasources=[]))
            beginRow += 1
        self.endInsertRows()
        assert self.rowCount() == oldRowCount+1, "oldRowCount = %d, self.rowCount() = %d" % (oldRowCount, self.rowCount())
        return True
            
    def removeRows(self, row, count, parent = QModelIndex()):
        '''Remove rows from the stack. 
        
        DO NOT USE THIS METHOD TO REMOVE LAYERS!
        Use the deleteSelected() method instead.
        
        '''

        if parent.isValid():
            return False
        if row+count <= 0 or row >= len(self._layerStack):
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0,row)
        endRow   = min(row+count-1, len(self._layerStack)-1)
        self.beginRemoveRows(parent, beginRow, endRow)
        while(beginRow <= endRow):
            del self._layerStack[row]
            beginRow += 1
        self.endRemoveRows()
        return True
    
    def flags(self, index):
        defaultFlags = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
        if index.isValid():
            return Qt.ItemIsDragEnabled | defaultFlags
        else:
            return Qt.ItemIsDropEnabled | defaultFlags
    
    def supportedDropActions(self):
        return Qt.MoveAction

    def data(self, index, role = Qt.DisplayRole):
        if not index.isValid():
            return None
        if index.row() > len(self._layerStack):
            return None
        
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._layerStack[index.row()]
        elif role == Qt.ToolTipRole:
            return self._layerStack[index.row()].toolTip()
        else:
            return None
    
    def setData(self, index, value, role = Qt.EditRole):
        '''Replace one layer with another. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Use deleteSelected() followed by insert() or append().
        
        '''
        if role == Qt.EditRole:
            layer = value
            if not isinstance(value, Layer):
                layer = value.toPyObject()
            self._layerStack[index.row()] = layer
            self.dataChanged.emit(index, index)
            return True
        elif role == Qt.ToolTipRole:
            self._layerStack[index.row()].setToolTip()
            return True
        return False
            
    
    def headerData(self, section, orientation, role = Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return "Column %r" % section
        else:
            return "Row %r" % section
        
    def wantsUpdate(self):
        self.layoutChanged.emit()

    def _onLayerChanged( self, idx ):
        self.dataChanged.emit(idx, idx)
        self.updateGUI()
        
    def _onSelectionChanged(self, selected, deselected):
        for idx in deselected.indexes():
            self[idx.row()].setActive(False) 
        for idx in selected.indexes():
            self[idx.row()].setActive(True) 
Exemplo n.º 33
0
    def __init__(self, parent=None, aptinkerQSettings=None):
        """Constructor"""

        QDialog.__init__(self, parent=parent)

        self.setupUi(self)

        self.setWindowFlags(Qt.Window) # To add Maximize & Minimize buttons
        self.setWindowTitle('Select Configuration from Database')

        # Load Startup Preferences for Config Table
        self.default_config_pref = dict(
            vis_col_key_list=config.DEF_VIS_COL_KEYS['config_setup'][:])
        if osp.exists(PREF_CONFIG_JSON_FILEPATH):
            with open(PREF_CONFIG_JSON_FILEPATH, 'r') as f:
                self.config_pref = json.load(f)
        else:
            self.config_pref = self.default_config_pref

        # Load Startup Preferences for Config Meta Table
        self.default_config_meta_pref = dict(
            vis_col_key_list=['config_id', 'config_ctime', 'config_name',
                              'username', 'config_ref_step_size',
                              'config_masar_id'])
        if osp.exists(PREF_CONFIG_META_JSON_FILEPATH):
            with open(PREF_CONFIG_META_JSON_FILEPATH, 'r') as f:
                self.config_meta_pref = json.load(f)
        else:
            self.config_meta_pref = self.default_config_meta_pref

        self.configDBViewWidget = ConfigDBViewWidget(
            self.groupBox_selected_conf)
        self.tableView_config = self.configDBViewWidget.tableView

        self.configMetaDBViewWidget = ConfigMetaDBViewWidget(
            self.groupBox_search_result)
        self.tableView_config_meta = self.configMetaDBViewWidget.tableView
        self.textEdit_description = \
            self.configMetaDBViewWidget.textEdit_description

        self.settings = QSettings('APHLA', 'TinkerConfigDBSelector')
        self.loadViewSettings()

        self._aptinkerQSettings = aptinkerQSettings

        self.pushButton_search.setIcon(QIcon(':/search.png'))

        all_ctime_operators = [
            self.comboBox_time_created_1.itemText(i)
            for i in range(self.comboBox_time_created_1.count())]
        self.comboBox_time_created_1.setCurrentIndex(
            all_ctime_operators.index(''))
        self.dateTimeEdit_time_created_1.setDateTime(
            QDateTime.currentDateTime())
        self.dateTimeEdit_time_created_2.setDateTime(
            QDateTime.currentDateTime())

        self.search_params = dict(
            config_id_1='', config_id_2='',
            ref_step_size_1='', ref_step_size_2='',
            config_name='', config_desc='', username='',
            ctime_1='', ctime_2='',
            synced_gruop_weight='',
            masar_id_1='', masar_id_2='')

        db_id_validator = QIntValidator()
        db_id_validator.setBottom(1)
        self.lineEdit_config_id_1.setValidator(db_id_validator)
        self.lineEdit_config_id_2.setValidator(db_id_validator)
        self.lineEdit_masar_id_1.setValidator(db_id_validator)
        self.lineEdit_masar_id_2.setValidator(db_id_validator)

        self.prev_valid_ref_step_sizes = dict(
            lineEdit_ref_step_size_1=np.nan, lineEdit_ref_step_size_2=np.nan)

        # Set up Config Table
        self.config_model = ConfigModel()
        self.tableModel_config = self.config_model.table
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_config)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_config
        tbV.setModel(proxyModel)
        tbV.setItemDelegate(ConfigDBTableViewItemDelegate(
            tbV, self.tableModel_config, tbV.parent()))

        self.db = self.config_model.db
        if '[config_meta_table text view]' not in self.db.getViewNames(
            square_brackets=True):
            self.db.create_temp_config_meta_table_text_view()

        # Set up Config Meta Table
        self.config_meta_all_col_keys = self.configMetaDBViewWidget.all_col_keys
        self.search_result = {k: [] for k in self.config_meta_all_col_keys}

        self.tableModel_config_meta = MetaTableModel(
            self.search_result, self.configMetaDBViewWidget)
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_config_meta)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_config_meta
        tbV.setModel(proxyModel)
        self.selectionModel = QItemSelectionModel(proxyModel)
        tbV.setSelectionModel(self.selectionModel)

        # Apply Visible Column Preference to Config Table
        (col_keys, col_names) = config.COL_DEF.getColumnDataFromTable(
            'column_table',
            column_name_list=['column_key','short_descrip_name'],
            condition_str='column_key in ({0:s})'.format(
                ','.join(['"{0:s}"'.format(k)
                          for k in self.config_pref['vis_col_key_list']]
                         )
            )
        )
        config_vis_col_name_list = [
            col_names[col_keys.index(k)]
            for k in self.config_pref['vis_col_key_list']]
        self.configDBViewWidget.on_column_selection_change(
            config_vis_col_name_list, force_visibility_update=True)

        # Apply Visible Column Preference to Config Meta Table
        config_meta_vis_col_name_list = [
            self.configMetaDBViewWidget.col_names_wo_desc[
                self.configMetaDBViewWidget.col_keys_wo_desc.index(k)]
            for k in self.config_meta_pref['vis_col_key_list']]
        self.configMetaDBViewWidget.on_column_selection_change(
            config_meta_vis_col_name_list, force_visibility_update=True)

        # Make connection

        self.connect(self.lineEdit_ref_step_size_1, SIGNAL('editingFinished()'),
                     self.validate_ref_step_size)
        self.connect(self.lineEdit_ref_step_size_2, SIGNAL('editingFinished()'),
                     self.validate_ref_step_size)

        self.connect(self.pushButton_search, SIGNAL('clicked()'),
                     self.update_search)

        self.connect(
            self.selectionModel,
            SIGNAL(
                'currentRowChanged(const QModelIndex &, const QModelIndex &)'),
            self.on_selection_change
        )

        self.connect(self.configMetaDBViewWidget, SIGNAL('exportConfigToFile'),
                     self.exportConfigToFile)
        self.connect(self.configMetaDBViewWidget,
                     SIGNAL('editConfigNameOrDescription'),
                     self.editConfigNameOrDescription)
Exemplo n.º 34
0
    def __init__(self, parent=None, aptinkerQSettings=None):
        """Constructor"""

        QDialog.__init__(self, parent=parent)

        self.setupUi(self)

        self.setWindowFlags(Qt.Window)  # To add Maximize & Minimize buttons
        self.setWindowTitle('Select Snapshot from Database')

        # Load Startup Preferences for Snapshot Table
        self.default_ss_pref = dict(
            vis_col_key_list=config.DEF_VIS_COL_KEYS['snapshot_DB'][:])
        if osp.exists(PREF_SS_JSON_FILEPATH):
            with open(PREF_SS_JSON_FILEPATH, 'r') as f:
                self.ss_pref = json.load(f)
        else:
            self.ss_pref = self.default_ss_pref

        # Load Startup Preferences for Snapshot Meta Table
        self.default_ss_meta_pref = dict(vis_col_key_list=[
            'ss_id', 'config_id', 'ss_ctime', 'ss_name', 'ss_username'
        ])
        if osp.exists(PREF_SS_META_JSON_FILEPATH):
            with open(PREF_SS_META_JSON_FILEPATH, 'r') as f:
                self.ss_meta_pref = json.load(f)
        else:
            self.ss_meta_pref = self.default_ss_meta_pref

        self.ssDBViewWidget = SnapshotDBViewWidget(self.groupBox_selected_ss,
                                                   DB_selector=True)
        self.tableView_ss = self.ssDBViewWidget.tableView

        self.ssMetaDBViewWidget = SnapshotMetaDBViewWidget(
            self.groupBox_search_result)
        self.tableView_ss_meta = self.ssMetaDBViewWidget.tableView
        self.textEdit_description = \
            self.ssMetaDBViewWidget.textEdit_description

        self.settings = QSettings('APHLA', 'TinkerSSDBSelector')
        self.loadViewSettings()

        self._aptinkerQSettings = aptinkerQSettings

        self.pushButton_search.setIcon(QIcon(':/search.png'))

        all_ctime_operators = [
            self.comboBox_time_created_1.itemText(i)
            for i in range(self.comboBox_time_created_1.count())
        ]
        self.comboBox_time_created_1.setCurrentIndex(
            all_ctime_operators.index(''))
        self.dateTimeEdit_time_created_1.setDateTime(
            QDateTime.currentDateTime())
        self.dateTimeEdit_time_created_2.setDateTime(
            QDateTime.currentDateTime())

        self.search_params = dict(ss_id_1='',
                                  ss_id_2='',
                                  config_id_1='',
                                  config_id_2='',
                                  ss_ref_step_size_1='',
                                  ss_ref_step_size_2='',
                                  ss_name='',
                                  ss_desc='',
                                  ss_username='',
                                  ss_ctime_1='',
                                  ss_ctime_2='',
                                  ss_synced_gruop_weight='',
                                  ss_masar_id_1='',
                                  ss_masar_id_2='')

        db_id_validator = QIntValidator()
        db_id_validator.setBottom(1)
        self.lineEdit_ss_id_1.setValidator(db_id_validator)
        self.lineEdit_ss_id_2.setValidator(db_id_validator)
        self.lineEdit_config_id_1.setValidator(db_id_validator)
        self.lineEdit_config_id_2.setValidator(db_id_validator)
        self.lineEdit_masar_id_1.setValidator(db_id_validator)
        self.lineEdit_masar_id_2.setValidator(db_id_validator)

        self.prev_valid_ref_step_sizes = dict(lineEdit_ref_step_size_1=np.nan,
                                              lineEdit_ref_step_size_2=np.nan)

        # Set up Snapshot Table
        self.ss_model = SnapshotModel(self.ss_pref['vis_col_key_list'])
        self.tableModel_ss = self.ss_model.table
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_ss)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_ss
        tbV.setModel(proxyModel)
        tbV.setItemDelegate(
            SnapshotDBTableViewItemDelegate(tbV, self.tableModel_ss,
                                            tbV.parent()))

        #self.db = TinkerMainDatabase()
        self.db = self.ss_model.db
        if '[ss_meta_table text view]' not in self.db.getViewNames(
                square_brackets=True):
            self.db.create_temp_ss_meta_table_text_view()

        # Set up Snapshot Meta Table
        self.ss_meta_all_col_keys = self.ssMetaDBViewWidget.all_col_keys
        self.search_result = {k: [] for k in self.ss_meta_all_col_keys}

        self.tableModel_ss_meta = MetaTableModel(self.search_result,
                                                 self.ssMetaDBViewWidget)
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_ss_meta)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_ss_meta
        tbV.setModel(proxyModel)
        self.selectionModel = QItemSelectionModel(proxyModel)
        tbV.setSelectionModel(self.selectionModel)

        # Apply Visible Column Preference to Snapshot Meta Table
        ss_meta_vis_col_name_list = [
            self.ssMetaDBViewWidget.col_names_wo_desc[
                self.ssMetaDBViewWidget.col_keys_wo_desc.index(k)]
            for k in self.ss_meta_pref['vis_col_key_list']
        ]
        self.ssMetaDBViewWidget.on_column_selection_change(
            ss_meta_vis_col_name_list, force_visibility_update=True)

        # Make connection

        self.connect(self.lineEdit_ref_step_size_1,
                     SIGNAL('editingFinished()'), self.validate_ref_step_size)
        self.connect(self.lineEdit_ref_step_size_2,
                     SIGNAL('editingFinished()'), self.validate_ref_step_size)

        self.connect(self.pushButton_search, SIGNAL('clicked()'),
                     self.update_search)

        self.connect(
            self.selectionModel,
            SIGNAL(
                'currentRowChanged(const QModelIndex &, const QModelIndex &)'),
            self.on_selection_change)
Exemplo n.º 35
0
class LabelListModel(QAbstractTableModel):
    orderChanged = pyqtSignal()
    labelSelected = pyqtSignal(int)
    
    def __init__(self, labels = [], parent = None):
        QAbstractTableModel.__init__(self, parent)
        self._labels = labels
        self._selectionModel = QItemSelectionModel(self)
        
        def onSelectionChanged(selected, deselected):
            if selected:
                self.labelSelected.emit(selected[0].indexes()[0].row())
        self._selectionModel.selectionChanged.connect(onSelectionChanged)
        
        self._allowRemove = True
    
    def __len__(self):
        return len(self._labels)
    
    def __getitem__(self, i):
        return self._labels[i]
     
    def selectedRow(self):
        selected = self._selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1
    
    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()
            
    def rowCount(self, parent=None):
        return len(self._labels)
    
    def columnCount(self, parent):
        return 3

    def data(self, index, role):
        if role == Qt.EditRole and index.column() == 0:
            return self._labels[index.row()].color
        if role == Qt.EditRole and index.column() == 1:
            return self._labels[index.row()].name
        
        if role == Qt.ToolTipRole and index.column() == 0:
            return "Hex code : " + self._labels[index.row()].color.name() + "\n DoubleClick to change"
        if role == Qt.ToolTipRole and index.column() == 1:
            return self._labels[index.row()].name + "\n DoubleClick to rename"
        if role == Qt.ToolTipRole and index.column() == 2:
            return "Delete " + self._labels[index.row()].name
        
        if role == Qt.DecorationRole and index.column() == 0:
            row = index.row()
            value = self._labels[row]
            pixmap = QPixmap(26, 26)
            pixmap.fill(value.color)
            icon = QIcon(pixmap)
            return icon
        
        if role == Qt.DecorationRole and index.column() == 2:
            row = index.row()
            pixmap = QPixmap(26, 26)
            pixmap.fill(Qt.transparent)
            painter = QPainter()
            painter.begin(pixmap)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setBrush(QColor("red"))
            painter.drawEllipse(1, 1, 24, 24)
            pen = QPen(QColor("black"))
            pen.setWidth(2)
            painter.setPen(pen)
            painter.drawLine(8,8, 18,18)
            painter.drawLine(18,8, 8,18)
            
            painter.end()
            icon = QIcon(pixmap)
            return icon
        
        if role == Qt.DisplayRole and index.column() == 1:
            row = index.row()
            value = self._labels[row]
            return value.name

    def flags(self, index):
        if  index.column() == 0:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif  index.column() == 1:
            return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif  index.column() == 2:
            if self._allowRemove:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                return Qt.NoItemFlags
        
    def setData(self, index, value, role = Qt.EditRole):
        if role == Qt.EditRole  and index.column() == 0:
            row = index.row()
            color = QColor(value)
            if color.isValid():
                self._labels[row].color = color
                self.dataChanged.emit(index, index)
                return True
            
        if role == Qt.EditRole  and index.column() == 1:
            row = index.row()
            name = value
            self._labels[row].name = str(name.toString())
            self.dataChanged.emit(index, index)
            return True
        return False

    def insertRow(self, position, object, parent = QModelIndex()):
        self.beginInsertRows(parent, position, position)
        self._labels.insert(position, object)
        self.endInsertRows()
        return True

    def removeRow(self, position, parent = QModelIndex()):
        self.beginRemoveRows(parent, position, position)
        value = self._labels[position]
        print "removing row: ", value
        self._labels.remove(value)     
        self.endRemoveRows()
        return True
    
    def allowRemove(self, check):
        #Allow removing of rows. Needed to be able to disallow it
        #in interactive mode
        self._allowRemove = check
        self.dataChanged.emit(self.createIndex(0, 2), self.createIndex(self.rowCount(), 2))

    def select(self, row):
        self._selectionModel.clear()
        self._selectionModel.select(self.index(row, 0), QItemSelectionModel.Select)
        self._selectionModel.select(self.index(row, 1), QItemSelectionModel.Select)
Exemplo n.º 36
0
class ConfigDBSelector(QDialog, Ui_Dialog):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent=None, aptinkerQSettings=None):
        """Constructor"""

        QDialog.__init__(self, parent=parent)

        self.setupUi(self)

        self.setWindowFlags(Qt.Window)  # To add Maximize & Minimize buttons
        self.setWindowTitle('Select Configuration from Database')

        # Load Startup Preferences for Config Table
        self.default_config_pref = dict(
            vis_col_key_list=config.DEF_VIS_COL_KEYS['config_setup'][:])
        if osp.exists(PREF_CONFIG_JSON_FILEPATH):
            with open(PREF_CONFIG_JSON_FILEPATH, 'r') as f:
                self.config_pref = json.load(f)
        else:
            self.config_pref = self.default_config_pref

        # Load Startup Preferences for Config Meta Table
        self.default_config_meta_pref = dict(vis_col_key_list=[
            'config_id', 'config_ctime', 'config_name', 'username',
            'config_ref_step_size', 'config_masar_id'
        ])
        if osp.exists(PREF_CONFIG_META_JSON_FILEPATH):
            with open(PREF_CONFIG_META_JSON_FILEPATH, 'r') as f:
                self.config_meta_pref = json.load(f)
        else:
            self.config_meta_pref = self.default_config_meta_pref

        self.configDBViewWidget = ConfigDBViewWidget(
            self.groupBox_selected_conf)
        self.tableView_config = self.configDBViewWidget.tableView

        self.configMetaDBViewWidget = ConfigMetaDBViewWidget(
            self.groupBox_search_result)
        self.tableView_config_meta = self.configMetaDBViewWidget.tableView
        self.textEdit_description = \
            self.configMetaDBViewWidget.textEdit_description

        self.settings = QSettings('APHLA', 'TinkerConfigDBSelector')
        self.loadViewSettings()

        self._aptinkerQSettings = aptinkerQSettings

        self.pushButton_search.setIcon(QIcon(':/search.png'))

        all_ctime_operators = [
            self.comboBox_time_created_1.itemText(i)
            for i in range(self.comboBox_time_created_1.count())
        ]
        self.comboBox_time_created_1.setCurrentIndex(
            all_ctime_operators.index(''))
        self.dateTimeEdit_time_created_1.setDateTime(
            QDateTime.currentDateTime())
        self.dateTimeEdit_time_created_2.setDateTime(
            QDateTime.currentDateTime())

        self.search_params = dict(config_id_1='',
                                  config_id_2='',
                                  ref_step_size_1='',
                                  ref_step_size_2='',
                                  config_name='',
                                  config_desc='',
                                  username='',
                                  ctime_1='',
                                  ctime_2='',
                                  synced_gruop_weight='',
                                  masar_id_1='',
                                  masar_id_2='')

        db_id_validator = QIntValidator()
        db_id_validator.setBottom(1)
        self.lineEdit_config_id_1.setValidator(db_id_validator)
        self.lineEdit_config_id_2.setValidator(db_id_validator)
        self.lineEdit_masar_id_1.setValidator(db_id_validator)
        self.lineEdit_masar_id_2.setValidator(db_id_validator)

        self.prev_valid_ref_step_sizes = dict(lineEdit_ref_step_size_1=np.nan,
                                              lineEdit_ref_step_size_2=np.nan)

        # Set up Config Table
        self.config_model = ConfigModel()
        self.tableModel_config = self.config_model.table
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_config)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_config
        tbV.setModel(proxyModel)
        tbV.setItemDelegate(
            ConfigDBTableViewItemDelegate(tbV, self.tableModel_config,
                                          tbV.parent()))

        self.db = self.config_model.db
        if '[config_meta_table text view]' not in self.db.getViewNames(
                square_brackets=True):
            self.db.create_temp_config_meta_table_text_view()

        # Set up Config Meta Table
        self.config_meta_all_col_keys = self.configMetaDBViewWidget.all_col_keys
        self.search_result = {k: [] for k in self.config_meta_all_col_keys}

        self.tableModel_config_meta = MetaTableModel(
            self.search_result, self.configMetaDBViewWidget)
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_config_meta)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_config_meta
        tbV.setModel(proxyModel)
        self.selectionModel = QItemSelectionModel(proxyModel)
        tbV.setSelectionModel(self.selectionModel)

        # Apply Visible Column Preference to Config Table
        (col_keys, col_names) = config.COL_DEF.getColumnDataFromTable(
            'column_table',
            column_name_list=['column_key', 'short_descrip_name'],
            condition_str='column_key in ({0:s})'.format(','.join([
                '"{0:s}"'.format(k)
                for k in self.config_pref['vis_col_key_list']
            ])))
        config_vis_col_name_list = [
            col_names[col_keys.index(k)]
            for k in self.config_pref['vis_col_key_list']
        ]
        self.configDBViewWidget.on_column_selection_change(
            config_vis_col_name_list, force_visibility_update=True)

        # Apply Visible Column Preference to Config Meta Table
        config_meta_vis_col_name_list = [
            self.configMetaDBViewWidget.col_names_wo_desc[
                self.configMetaDBViewWidget.col_keys_wo_desc.index(k)]
            for k in self.config_meta_pref['vis_col_key_list']
        ]
        self.configMetaDBViewWidget.on_column_selection_change(
            config_meta_vis_col_name_list, force_visibility_update=True)

        # Make connection

        self.connect(self.lineEdit_ref_step_size_1,
                     SIGNAL('editingFinished()'), self.validate_ref_step_size)
        self.connect(self.lineEdit_ref_step_size_2,
                     SIGNAL('editingFinished()'), self.validate_ref_step_size)

        self.connect(self.pushButton_search, SIGNAL('clicked()'),
                     self.update_search)

        self.connect(
            self.selectionModel,
            SIGNAL(
                'currentRowChanged(const QModelIndex &, const QModelIndex &)'),
            self.on_selection_change)

        self.connect(self.configMetaDBViewWidget, SIGNAL('exportConfigToFile'),
                     self.exportConfigToFile)
        self.connect(self.configMetaDBViewWidget,
                     SIGNAL('editConfigNameOrDescription'),
                     self.editConfigNameOrDescription)

    #----------------------------------------------------------------------
    def exportConfigToFile(self):
        """"""

        msg = QMessageBox()

        inds = self.selectionModel.selectedRows()

        if inds != []:
            row = inds[0].row()
            config_id = self.search_result['config_id'][row]
            saved_filepath = self.config_model.abstract.exportToFile(
                config_id, self._aptinkerQSettings)
            if saved_filepath:
                msg.setText(
                    'Successfully exported config (ID={0:d}) to the file "{1}".'
                    .format(config_id, saved_filepath))
                msg.exec_()
        else:
            msg.setText('You must select a configuration to be exported.')
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()

    #----------------------------------------------------------------------
    def editConfigNameOrDescription(self):
        """"""

        msg = QMessageBox()

        inds = self.selectionModel.selectedRows()

        if inds != []:
            row = inds[0].row()
            config_id = self.search_result['config_id'][row]

            title = 'Edit Config Name or Description'
            prompt = 'Property to Edit:'
            result = QInputDialog.getItem(self,
                                          title,
                                          prompt, ['Name', 'Description'],
                                          current=1,
                                          editable=False)

            if result[1]:
                table_name = 'config_meta_text_search_table'
                if result[0] == 'Name':
                    current_name, current_desc = self.db.getColumnDataFromTable(
                        table_name,
                        column_name_list=['config_name', 'config_description'],
                        condition_str='config_id={0:d}'.format(config_id))
                    current_name = current_name[0]
                    current_desc = current_desc[0]

                    title = 'Edit Config Name'
                    prompt = 'Enter a new name:'
                    result = QInputDialog.getText(self,
                                                  title,
                                                  prompt,
                                                  text=current_name)

                    if result[1]:
                        new_name = result[0]

                        mod_time_str = datestr(time.time())
                        new_desc = current_desc + ((
                            '\n### Modified by "{0}" on {1}###\n  Config Name '
                            'changed from "{2}" to "{3}"\n').format(
                                getusername(), mod_time_str, current_name,
                                new_name))

                        self.db.changeValues(
                            table_name,
                            'config_name',
                            '"{0}"'.format(new_name.replace('"', '""')),
                            condition_str='config_id={0:d}'.format(config_id))
                        self.db.changeValues(
                            table_name,
                            'config_description',
                            '"{0}"'.format(new_desc.replace('"', '""')),
                            condition_str='config_id={0:d}'.format(config_id))

                        # Update Config Meta DB Table
                        row = self.search_result['config_id'].index(config_id)
                        self.search_result['config_name'][row] = new_name
                        self.search_result['config_description'][
                            row] = new_desc
                        self.tableModel_config_meta.repaint()
                        self.on_selection_change(None, None)

                else:
                    current_desc, = self.db.getColumnDataFromTable(
                        table_name,
                        column_name_list=['config_description'],
                        condition_str='config_id={0:d}'.format(config_id))
                    current_desc = current_desc[0]

                    dialog = ConfigDescriptionEditor(current_desc, parent=self)
                    dialog.exec_()

                    if dialog.result() == QDialog.Accepted:
                        mod_time_str = datestr(time.time())
                        temp_new_desc = dialog.plainTextEdit_new.property(
                            'plainText')

                        new_desc = current_desc + (
                            ('\n### Modified by "{0}" on {1}###\n{2}\n'.format(
                                getusername(), mod_time_str, temp_new_desc)))

                        self.db.changeValues(
                            table_name,
                            'config_description',
                            '"{0}"'.format(new_desc.replace('"', '""')),
                            condition_str='config_id={0:d}'.format(config_id))

                        # Update Config Meta DB Table
                        row = self.search_result['config_id'].index(config_id)
                        self.search_result['config_description'][
                            row] = new_desc
                        self.tableModel_config_meta.repaint()
                        self.on_selection_change(None, None)

        else:
            msg.setText('You must select a configuration whose name or '
                        'description to be edited.')
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()

    #----------------------------------------------------------------------
    def closeEvent(self, event):
        """"""

        self.saveViewSettings()

        self.config_model.abstract.channel_ids = []

        event.accept()

    #----------------------------------------------------------------------
    def accept(self):
        """"""

        a = self.config_model.abstract

        if not a.isDataValid():
            return

        if not a.check_aphla_unitconv_updates():
            return

        self.saveViewSettings()

        super(ConfigDBSelector, self).accept()  # will close the dialog

    #----------------------------------------------------------------------
    def reject(self):
        """"""

        self.config_model.abstract.channel_ids = []

        self.saveViewSettings()

        super(ConfigDBSelector, self).reject()  # will close the dialog

    #----------------------------------------------------------------------
    def loadViewSettings(self):
        """"""

        self.settings.beginGroup('viewSize')

        rect = self.settings.value('position')
        if not rect:
            rect = QRect(0, 0,
                         self.sizeHint().width(),
                         self.sizeHint().height())
        self.setGeometry(rect)

        splitter_sizes = self.settings.value('splitter_1')
        if splitter_sizes is None:
            splitter_sizes = [self.width() * (1. / 2), self.width() * (1. / 2)]
        else:
            splitter_sizes = [int(s) for s in splitter_sizes]
        self.splitter.setSizes(splitter_sizes)

        splitter_sizes = self.settings.value('splitter_2')
        if splitter_sizes is None:
            splitter_sizes = [self.width() * (1. / 5), self.width() * (4. / 5)]
        else:
            splitter_sizes = [int(s) for s in splitter_sizes]
        self.splitter_2.setSizes(splitter_sizes)

        splitter_sizes = self.settings.value('splitter_3')
        if splitter_sizes is None:
            splitter_sizes = [
                self.configMetaDBViewWidget.height() * (2. / 3),
                self.configMetaDBViewWidget.height() * (1. / 3)
            ]
        else:
            splitter_sizes = [int(s) for s in splitter_sizes]
        self.configMetaDBViewWidget.splitter.setSizes(splitter_sizes)

        self.settings.endGroup()

    #----------------------------------------------------------------------
    def saveViewSettings(self):
        """"""

        self.settings.beginGroup('viewSize')

        self.settings.setValue('position', self.geometry())

        self.settings.setValue('splitter_1', self.splitter.sizes())
        self.settings.setValue('splitter_2', self.splitter_2.sizes())
        self.settings.setValue('splitter_3',
                               self.configMetaDBViewWidget.splitter.sizes())

        self.settings.endGroup()

    #----------------------------------------------------------------------
    def validate_ref_step_size(self):
        """"""

        sender = self.sender()
        name = sender.objectName()
        text = sender.text().strip()
        if text == '':
            text = 'nan'

        try:
            new_float = float(text)
            if np.isnan(new_float):
                sender.setText('')
            self.prev_valid_ref_step_sizes[name] = new_float
        except:
            msg = QMessageBox()
            msg.setText('Invalid float string: {0:s}'.format(text))
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()
            if np.isnan(self.prev_valid_ref_step_sizes[name]):
                sender.setText('')
            else:
                sender.setText(str(self.prev_valid_ref_step_sizes[name]))

    #----------------------------------------------------------------------
    def update_search(self):
        """"""

        try:
            config_id_1_text = str(int(self.lineEdit_config_id_1.text()))
        except:
            config_id_1_text = ''
        try:
            config_id_2_text = str(int(self.lineEdit_config_id_2.text()))
        except:
            config_id_2_text = ''
        config_id_1_operator = \
            self.comboBox_config_id_1.currentText().strip()
        config_id_2_operator = \
            self.comboBox_config_id_2.currentText().strip()
        if (config_id_1_text != '') and (config_id_1_operator != ''):
            self.search_params['config_id_1'] = (
                'config_id {0:s} {1:s}'.format(config_id_1_operator,
                                               config_id_1_text))
        else:
            self.search_params['config_id_1'] = ''
        if (config_id_2_text != '') and (config_id_2_operator != ''):
            self.search_params['config_id_2'] = (
                'config_id {0:s} {1:s}'.format(config_id_2_operator,
                                               config_id_2_text))
        else:
            self.search_params['config_id_2'] = ''

        try:
            masar_id_1_text = str(int(self.lineEdit_masar_id_1.text()))
        except:
            masar_id_1_text = ''
        try:
            masar_id_2_text = str(int(self.lineEdit_masar_id_2.text()))
        except:
            masar_id_2_text = ''
        masar_id_1_operator = \
            self.comboBox_masar_id_1.currentText().strip()
        masar_id_2_operator = \
            self.comboBox_masar_id_2.currentText().strip()
        if (masar_id_1_text != '') and (masar_id_1_operator != ''):
            self.search_params['masar_id_1'] = (
                'config_masar_id {0:s} {1:s}'.format(masar_id_1_operator,
                                                     masar_id_1_text))
        else:
            self.search_params['masar_id_1'] = ''
        if (masar_id_2_text != '') and (masar_id_2_operator != ''):
            self.search_params['masar_id_2'] = (
                'config_masar_id {0:s} {1:s}'.format(masar_id_2_operator,
                                                     masar_id_2_text))
        else:
            self.search_params['masar_id_2'] = ''

        try:
            ref_step_size_1_text = '{0:.9e}'.format(
                float(self.lineEdit_ref_step_size_1.text()))
        except:
            ref_step_size_1_text = ''
        try:
            ref_step_size_2_text = '{0:.9e}'.format(
                float(self.lineEdit_ref_step_size_2.text()))
        except:
            ref_step_size_2_text = ''
        ref_step_size_1_operator = \
            self.comboBox_ref_step_size_1.currentText().strip()
        ref_step_size_2_operator = \
            self.comboBox_ref_step_size_2.currentText().strip()
        if (ref_step_size_1_text != '') and (ref_step_size_1_operator != ''):
            self.search_params['ref_step_size_1'] = (
                'config_ref_step_size {0:s} {1:s}'.format(
                    ref_step_size_1_operator, ref_step_size_1_text))
        else:
            self.search_params['ref_step_size_1'] = ''
        if (ref_step_size_2_text != '') and (ref_step_size_2_operator != ''):
            self.search_params['ref_step_size_2'] = (
                'config_ref_step_size {0:s} {1:s}'.format(
                    ref_step_size_2_operator, ref_step_size_2_text))
        else:
            self.search_params['ref_step_size_2'] = ''

        synced_group_weight_text = \
            self.comboBox_synced_group_weight.currentText()
        if synced_group_weight_text == 'False':
            self.search_params['synced_group_weight'] = \
                'config_synced_group_weight = 0'
        elif synced_group_weight_text == 'True':
            self.search_params['synced_group_weight'] = \
                'config_synced_group_weight = 1'
        else:
            self.search_params['synced_group_weight'] = ''

        config_name_text = self.lineEdit_config_name.text().strip()
        if config_name_text != '':
            cond_str = self.db.get_MATCH_condition_str(config_name_text)
            if cond_str is not None:
                try:
                    self.search_params['config_name'] = \
                        self.db.get_config_ids_with_MATCH(cond_str, 'config_name')
                except:
                    msg = QMessageBox()
                    msg.setText('Invalid search strings for "Config Name"')
                    msg.setInformativeText(sys.exc_info()[1].__repr__())
                    msg.setIcon(QMessageBox.Critical)
                    msg.exec_()
                    return
            else:
                return
        else:
            self.search_params['config_name'] = []

        config_desc_text = self.lineEdit_config_description.text().strip()
        if config_desc_text != '':
            cond_str = self.db.get_MATCH_condition_str(config_desc_text)
            if cond_str is not None:
                try:
                    self.search_params['config_description'] = \
                        self.db.get_config_ids_with_MATCH(cond_str, 'config_description')
                except:
                    msg = QMessageBox()
                    msg.setText(
                        'Invalid search strings for "Config Description"')
                    msg.setInformativeText(sys.exc_info()[1].__repr__())
                    msg.setIcon(QMessageBox.Critical)
                    msg.exec_()
                    return
            else:
                return
        else:
            self.search_params['config_description'] = []

        username_text = self.lineEdit_username.text().strip()
        if username_text != '':
            self.search_params['username'] = \
                self.db.get_GLOB_condition_str(username_text, 'username')
        else:
            self.search_params['username'] = ''

        ctime_1_operator = self.comboBox_time_created_1.currentText().strip()
        if ctime_1_operator != '':
            ctime_epoch_1 = self.dateTimeEdit_time_created_1.dateTime()
            ctime_epoch_1 = time.mktime(
                ctime_epoch_1.toPyDateTime().timetuple())
            self.search_params['ctime_1'] = (
                'config_ctime {0:s} {1:.3f}'.format(ctime_1_operator,
                                                    ctime_epoch_1))
        else:
            self.search_params['ctime_1'] = ''
        ctime_2_operator = self.comboBox_time_created_2.currentText().strip()
        if ctime_2_operator != '':
            ctime_epoch_2 = self.dateTimeEdit_time_created_2.dateTime()
            ctime_epoch_2 = time.mktime(
                ctime_epoch_2.toPyDateTime().timetuple())
            self.search_params['ctime_2'] = (
                'config_ctime {0:s} {1:.3f}'.format(ctime_2_operator,
                                                    ctime_epoch_2))
        else:
            self.search_params['ctime_2'] = ''

        if (self.search_params['config_name'] is None) or \
           (self.search_params['config_description'] is None):
            for k in self.config_meta_all_col_keys:
                self.search_result[k] = []
        else:
            condition_str = ''
            for k, v in self.search_params.iteritems():
                if k in ('config_name', 'config_description'):
                    if v:
                        if condition_str != '':
                            condition_str += ' AND '
                        condition_str += '(config_id IN ({0:s}))'.format(
                            ','.join([str(i) for i in v]))
                else:
                    if v:
                        if condition_str != '':
                            condition_str += ' AND '
                        condition_str += '({0:s})'.format(v)
            out = self.db.getColumnDataFromTable(
                '[config_meta_table text view]',
                column_name_list=self.config_meta_all_col_keys,
                condition_str=condition_str,
                order_by_str='config_id')
            if out != []:
                if self.checkBox_hide_NG.isChecked():
                    config_name_col_ind = self.config_meta_all_col_keys.index(
                        'config_name')
                    valid_indexes = [
                        i for i, name in enumerate(out[config_name_col_ind])
                        if '$NG$' not in name
                    ]
                else:
                    valid_indexes = range(len(out[0]))
                for k, v in zip(self.config_meta_all_col_keys, out):
                    self.search_result[k] = [
                        x for i, x in enumerate(v) if i in valid_indexes
                    ]
            else:
                for k in self.config_meta_all_col_keys:
                    self.search_result[k] = []

        self.tableModel_config_meta.repaint()

        self.on_selection_change(None, None)

    #----------------------------------------------------------------------
    def convert_GLOB_to_LIKE_wildcards(self, char):
        """"""

        if char == '*':
            return '%'
        elif char == '?':
            return '_'
        else:
            raise ValueError('Unexpected char: {0:s}'.format(char))

    #----------------------------------------------------------------------
    def get_LIKE_condition_str(self, glob_pattern, column_name):
        """"""

        backslahs_inds = [i for i, c in enumerate(glob_pattern) if c == '\\']
        like_pattern = ''.join([
            self.convert_GLOB_to_LIKE_wildcards(c) if
            (c in ('*', '?')) and (i - 1 not in backslahs_inds) else c
            for i, c in enumerate(glob_pattern)
        ])
        cond_str = '({0:s} LIKE "{1:s}" ESCAPE "\\")'.format(
            column_name, like_pattern)

        return cond_str

    #----------------------------------------------------------------------
    def on_selection_change(self, current_index, previous_index):
        """"""

        a = self.config_model.abstract

        if current_index is None:
            self.textEdit_description.setText('')
            a.ref_step_size = np.nan
            (a.group_name_ids, a.channel_ids, a.weights,
             a.caput_enabled_rows) = [], [], [], []
        else:
            row = current_index.row()

            a.config_id = self.search_result['config_id'][row]
            a.name = self.search_result['config_name'][row]
            a.description = self.search_result['config_description'][row]
            a.config_ctime = self.search_result['config_ctime'][row]

            self.textEdit_description.setText(a.description)

            a.ref_step_size = self.search_result['config_ref_step_size'][row]
            out = self.db.getColumnDataFromTable(
                'config_table',
                column_name_list=[
                    'group_name_id', 'channel_id', 'config_weight',
                    'config_caput_enabled'
                ],
                condition_str='config_id={0:d}'.format(
                    self.search_result['config_id'][row]))

            if out != []:
                (a.group_name_ids, a.channel_ids, a.weights,
                 a.caput_enabled_rows) = map(list, out)
            else:
                (a.group_name_ids, a.channel_ids, a.weights,
                 a.caput_enabled_rows) = [], [], [], []

            a.weights = [w if w is not None else np.nan for w in a.weights]

        self.config_model.table.updateModel()
        self.config_model.table.repaint()
Exemplo n.º 37
0
class MainWindow(QMainWindow):
    def __init__(self, labeltool, parent=None):
        QMainWindow.__init__(self, parent)

        self.idletimer = QTimer()
        self.loader = None

        self.labeltool = labeltool
        self.setupGui()
        self.loadApplicationSettings()
        self.onAnnotationsLoaded()

    # Slots
    def onPluginLoaded(self, action):
        self.ui.menuPlugins.addAction(action)

    def onStatusMessage(self, message=''):
        self.statusBar().showMessage(message, 5000)

    def onModelDirtyChanged(self, dirty):
        postfix = "[+]" if dirty else ""
        if self.labeltool.getCurrentFilename() is not None:
            self.setWindowTitle("%s - %s %s" % \
                (APP_NAME, QFileInfo(self.labeltool.getCurrentFilename()).fileName(), postfix))
        else:
            self.setWindowTitle("%s - Unnamed %s" % (APP_NAME, postfix))

    def onMousePositionChanged(self, x, y):
        self.posinfo.setText("%d, %d" % (x, y))

    def startBackgroundLoading(self):
        self.stopBackgroundLoading(forced=True)
        self.loader = BackgroundLoader(self.labeltool.model(),
                                       self.statusBar(), self.sb_progress)
        self.idletimer.timeout.connect(self.loader.load)
        self.loader.finished.connect(self.stopBackgroundLoading)
        self.statusBar().addWidget(self.sb_progress)
        self.sb_progress.show()
        self.idletimer.start()

    def stopBackgroundLoading(self, forced=False):
        if not forced:
            self.statusBar().showMessage("Background loading finished", 5000)
        self.idletimer.stop()
        if self.loader is not None:
            self.idletimer.timeout.disconnect(self.loader.load)
            self.statusBar().removeWidget(self.sb_progress)
            self.loader = None

    def onAnnotationsLoaded(self):
        self.labeltool.model().dirtyChanged.connect(self.onModelDirtyChanged)
        self.onModelDirtyChanged(self.labeltool.model().dirty())
        self.treeview.setModel(self.labeltool.model())
        self.scene.setModel(self.labeltool.model())
        self.selectionmodel = QItemSelectionModel(self.labeltool.model())
        self.treeview.setSelectionModel(self.selectionmodel)
        self.treeview.selectionModel().currentChanged.connect(
            self.labeltool.setCurrentImage)
        self.property_editor.onModelChanged(self.labeltool.model())
        self.startBackgroundLoading()

    def onCurrentImageChanged(self):
        new_image = self.labeltool.currentImage()
        self.scene.setCurrentImage(new_image)
        self.onFitToWindowModeChanged()
        self.treeview.scrollTo(new_image.index())

        img = self.labeltool.getImage(new_image)

        if img == None:
            self.controls.setFilename("")
            self.selectionmodel.setCurrentIndex(
                new_image.index(),
                QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
            return

        h = img.shape[0]
        w = img.shape[1]
        self.image_resolution.setText("%dx%d" % (w, h))

        # TODO: This info should be obtained from AnnotationModel or LabelTool
        if isinstance(new_image, FrameModelItem):
            self.controls.setFrameNumAndTimestamp(new_image.framenum(),
                                                  new_image.timestamp())
        elif isinstance(new_image, ImageFileModelItem):
            self.controls.setFilename(os.path.basename(new_image['filename']))

        self.selectionmodel.setCurrentIndex(
            new_image.index(),
            QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)

    def onFitToWindowModeChanged(self):
        if self.options["Fit-to-window mode"].isChecked():
            self.view.fitInView()

    def onEnumerateCornersModeChanged(self):
        if self.options["Enumerate-corners mode"].isChecked():
            self.scene.enumerateCorners()
            self.onCurrentImageChanged()
        else:
            self.scene.removeCorners()
            self.onCurrentImageChanged()

    def onCopyAnnotationsModeChanged(self):
        if self.annotationMenu["Copy from previous"].isChecked():
            self.copyAnnotations.copy()
            self.annotationMenu["Copy from previous"].setChecked(False)

    def onInterpolateRangeModeChanged(self):
        if self.annotationMenu["Interpolate range"].isChecked():
            self.interpolateRange.interpolateRange()
            self.annotationMenu["Interpolate range"].setChecked(False)

    def onScaleChanged(self, scale):
        self.zoominfo.setText("%.2f%%" % (100 * scale, ))

    def initShortcuts(self, HOTKEYS):
        self.shortcuts = []

        for hotkey in HOTKEYS:
            assert len(hotkey) >= 2
            key = hotkey[0]
            fun = hotkey[1]
            desc = ""
            if len(hotkey) > 2:
                desc = hotkey[2]
            if type(fun) == str:
                fun = import_callable(fun)

            hk = QAction(desc, self)
            hk.setShortcut(QKeySequence(key))
            hk.setEnabled(True)
            if hasattr(fun, '__call__'):
                hk.triggered.connect(bind(fun, self.labeltool))
            else:
                hk.triggered.connect(
                    compose_noargs([bind(f, self.labeltool) for f in fun]))
            self.ui.menuShortcuts.addAction(hk)
            self.shortcuts.append(hk)

    def initOptions(self):
        self.options = {}
        for o in ["Fit-to-window mode"]:
            action = QAction(o, self)
            action.setCheckable(True)
            self.ui.menuOptions.addAction(action)
            self.options[o] = action

        for o in ["Enumerate-corners mode"]:
            action = QAction(o, self)
            action.setCheckable(True)
            self.ui.menuOptions.addAction(action)
            self.options[o] = action

    def initAnnotationMenu(self):
        self.annotationMenu = {}
        for a in ["Copy from previous"]:
            action = QAction(a, self)
            action.setCheckable(True)
            self.ui.menuAnnotation.addAction(action)
            self.annotationMenu[a] = action

        for a in ["Interpolate range"]:
            action = QAction(a, self)
            action.setCheckable(True)
            self.ui.menuAnnotation.addAction(action)
            self.annotationMenu[a] = action

    ###
    ### GUI/Application setup
    ###___________________________________________________________________________________________
    def setupGui(self):
        self.ui = uic.loadUi(os.path.join(GUIDIR, "labeltool.ui"), self)

        # get inserters and items from labels
        # FIXME for handling the new-style config correctly
        inserters = dict([
            (label['attributes']['class'], label['inserter'])
            for label in config.LABELS
            if 'class' in label.get('attributes', {}) and 'inserter' in label
        ])
        items = dict([
            (label['attributes']['class'], label['item'])
            for label in config.LABELS
            if 'class' in label.get('attributes', {}) and 'item' in label
        ])

        # Property Editor
        self.property_editor = PropertyEditor(config.LABELS)
        self.ui.dockProperties.setWidget(self.property_editor)

        # Scene
        self.scene = AnnotationScene(self.labeltool,
                                     items=items,
                                     inserters=inserters)
        self.property_editor.insertionModeStarted.connect(
            self.scene.onInsertionModeStarted)
        self.property_editor.insertionModeEnded.connect(
            self.scene.onInsertionModeEnded)

        # SceneView
        self.view = GraphicsView(self)
        self.view.setSizePolicy(QSizePolicy.MinimumExpanding,
                                QSizePolicy.MinimumExpanding)
        self.view.setScene(self.scene)

        self.central_widget = QWidget()
        self.central_layout = QVBoxLayout()
        self.controls = ControlButtonWidget()
        self.controls.back_button.clicked.connect(self.labeltool.gotoPrevious)
        self.controls.forward_button.clicked.connect(self.labeltool.gotoNext)

        self.central_layout.addWidget(self.controls)
        self.central_layout.addWidget(self.view)
        self.central_widget.setLayout(self.central_layout)
        self.setCentralWidget(self.central_widget)

        self.initShortcuts(config.HOTKEYS)
        self.initOptions()
        self.initAnnotationMenu()

        self.treeview = AnnotationTreeView()
        self.treeview.setSizePolicy(QSizePolicy.MinimumExpanding,
                                    QSizePolicy.Preferred)
        self.ui.dockAnnotations.setWidget(self.treeview)

        self.scene.selectionChanged.connect(self.scene.onSelectionChanged)
        self.treeview.selectedItemsChanged.connect(
            self.scene.onSelectionChangedInTreeView)

        self.posinfo = QLabel("-1, -1")
        self.posinfo.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.posinfo)
        self.scene.mousePositionChanged.connect(self.onMousePositionChanged)

        self.image_resolution = QLabel("[no image]")
        self.image_resolution.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.image_resolution)

        self.zoominfo = QLabel()
        self.zoominfo.setFrameStyle(QFrame.StyledPanel)
        self.statusBar().addPermanentWidget(self.zoominfo)
        self.view.scaleChanged.connect(self.onScaleChanged)
        self.onScaleChanged(self.view.getScale())

        self.sb_progress = QProgressBar()

        # View menu
        self.ui.menu_Views.addAction(self.ui.dockProperties.toggleViewAction())
        self.ui.menu_Views.addAction(
            self.ui.dockAnnotations.toggleViewAction())

        # Annotation menu
        self.copyAnnotations = CopyAnnotations(self.labeltool)
        self.interpolateRange = InterpolateRange(self.labeltool)

        # Show the UI.  It is important that this comes *after* the above
        # adding of custom widgets, especially the central widget.  Otherwise the
        # dock widgets would be far to large.
        self.ui.show()

        ## connect action signals
        self.connectActions()

    def connectActions(self):
        ## File menu
        self.ui.actionNew.triggered.connect(self.fileNew)
        self.ui.actionOpen.triggered.connect(self.fileOpen)
        self.ui.actionSave.triggered.connect(self.fileSave)
        self.ui.actionSave_As.triggered.connect(self.fileSaveAs)
        self.ui.actionExit.triggered.connect(self.close)

        ## View menu
        self.ui.actionLocked.toggled.connect(self.onViewsLockedChanged)

        ## Help menu
        self.ui.action_About.triggered.connect(self.about)

        ## Navigation
        self.ui.action_Add_Image.triggered.connect(self.addMediaFile)
        self.ui.actionNext.triggered.connect(self.labeltool.gotoNext)
        self.ui.actionPrevious.triggered.connect(self.labeltool.gotoPrevious)
        self.ui.actionZoom_In.triggered.connect(
            functools.partial(self.view.setScaleRelative, 1.2))
        self.ui.actionZoom_Out.triggered.connect(
            functools.partial(self.view.setScaleRelative, 1 / 1.2))

        ## Connections to LabelTool
        self.labeltool.pluginLoaded.connect(self.onPluginLoaded)
        self.labeltool.statusMessage.connect(self.onStatusMessage)
        self.labeltool.annotationsLoaded.connect(self.onAnnotationsLoaded)
        self.labeltool.currentImageChanged.connect(self.onCurrentImageChanged)

        ## options menu
        self.options["Fit-to-window mode"].changed.connect(
            self.onFitToWindowModeChanged)
        self.options["Enumerate-corners mode"].changed.connect(
            self.onEnumerateCornersModeChanged)

        ## annotation menu
        self.annotationMenu["Copy from previous"].changed.connect(
            self.onCopyAnnotationsModeChanged)
        self.annotationMenu["Interpolate range"].changed.connect(
            self.onInterpolateRangeModeChanged)

    def loadApplicationSettings(self):
        settings = QSettings()
        size = settings.value("MainWindow/Size", QSize(800, 600))
        pos = settings.value("MainWindow/Position", QPoint(10, 10))
        state = settings.value("MainWindow/State")
        locked = settings.value("MainWindow/ViewsLocked", False)
        if isinstance(size, QVariant): size = size.toSize()
        if isinstance(pos, QVariant): pos = pos.toPoint()
        if isinstance(state, QVariant): state = state.toByteArray()
        if isinstance(locked, QVariant): locked = locked.toBool()
        self.resize(size)
        self.move(pos)
        if state is not None:
            self.restoreState(state)
        self.ui.actionLocked.setChecked(bool(locked))

    def saveApplicationSettings(self):
        settings = QSettings()
        settings.setValue("MainWindow/Size", self.size())
        settings.setValue("MainWindow/Position", self.pos())
        settings.setValue("MainWindow/State", self.saveState())
        settings.setValue("MainWindow/ViewsLocked",
                          self.ui.actionLocked.isChecked())
        if self.labeltool.getCurrentFilename() is not None:
            filename = self.labeltool.getCurrentFilename()
        else:
            filename = None
        settings.setValue("LastFile", filename)

    def okToContinue(self):
        if self.labeltool.model().dirty():
            reply = QMessageBox.question(
                self, "%s - Unsaved Changes" % (APP_NAME),
                "Save unsaved changes?",
                QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
            if reply == QMessageBox.Cancel:
                return False
            elif reply == QMessageBox.Yes:
                return self.fileSave()
        return True

    def fileNew(self):
        if self.okToContinue():
            self.labeltool.clearAnnotations()

    def fileOpen(self):
        if not self.okToContinue():
            return
        path = '.'
        filename = self.labeltool.getCurrentFilename()
        if (filename is not None) and (len(filename) > 0):
            path = QFileInfo(filename).path()

        format_str = ' '.join(self.labeltool.getAnnotationFilePatterns())
        fname = QFileDialog.getOpenFileName(
            self, "%s - Load Annotations" % APP_NAME, path,
            "%s annotation files (%s)" % (APP_NAME, format_str))
        if len(str(fname)) > 0:
            self.labeltool.loadAnnotations(fname)

    def fileSave(self):
        filename = self.labeltool.getCurrentFilename()
        if filename is None:
            return self.fileSaveAs()
        return self.labeltool.saveAnnotations(filename)

    def fileSaveAs(self):
        fname = '.'  # self.annotations.filename() or '.'
        format_str = ' '.join(self.labeltool.getAnnotationFilePatterns())
        fname = QFileDialog.getSaveFileName(
            self, "%s - Save Annotations" % APP_NAME, fname,
            "%s annotation files (%s)" % (APP_NAME, format_str))

        if len(str(fname)) > 0:
            return self.labeltool.saveAnnotations(str(fname))
        return False

    def addMediaFile(self):
        filename = self.labeltool.getCurrentFilename()

        image_types = [
            '*.jpg', '*.bmp', '*.png', '*.pgm', '*.ppm', '*.ppm', '*.tif',
            '*.gif'
        ]
        video_types = [
            '*.mp4', '*.mpg', '*.mpeg', '*.avi', '*.mov', '*.vob', '*.json'
        ]
        format_str = ' '.join(image_types + video_types)
        fnames = QFileDialog.getOpenFileNames(
            self, "%s - Add Media File" % APP_NAME, path,
            "Media files (%s)" % (format_str, ))

        item = None
        numFiles = len(fnames)
        progress_bar = QProgressDialog('Importing files...', 'Cancel import',
                                       0, numFiles, self)
        for fname, c in zip(fnames, range(numFiles)):
            if len(str(fname)) == 0:
                continue

            fname = str(fname)

            if os.path.isabs(fname):
                fname = os.path.relpath(fname)

            for pattern in image_types:
                if fnmatch.fnmatch(fname, pattern):
                    item = self.labeltool.addImageFile(fname)

            progress_bar.setValue(c)

        if item is None:
            item = self.labeltool.addVideoFile(fname, progress_bar)

        progress_bar.close()

        return item

    def onViewsLockedChanged(self, checked):
        features = QDockWidget.AllDockWidgetFeatures
        if checked:
            features = QDockWidget.NoDockWidgetFeatures

        self.ui.dockProperties.setFeatures(features)
        self.ui.dockAnnotations.setFeatures(features)

    ###
    ### global event handling
    ###______________________________________________________________________________
    def closeEvent(self, event):
        if self.okToContinue():
            self.saveApplicationSettings()
        else:
            event.ignore()

    def about(self):
        QMessageBox.about(
            self, "About %s" % APP_NAME, """<b>%s</b> version %s
             <p>This labeling application for computer vision research
             was developed at the CVHCI research group at KIT.
             <p>For more details, visit our homepage: <a href="%s">%s</a>""" %
            (APP_NAME, __version__, ORGANIZATION_DOMAIN, ORGANIZATION_DOMAIN))
Exemplo n.º 38
0
class LabelListModel(QAbstractTableModel):
    orderChanged = pyqtSignal()
    labelSelected = pyqtSignal(int)

    def __init__(self, labels=None, parent=None):
        QAbstractTableModel.__init__(self, parent)

        if labels is None:
            labels = []
        self._labels = list(labels)
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):
            if selected:
                self.labelSelected.emit(selected[0].indexes()[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}

    def __len__(self):
        return len(self._labels)

    def __getitem__(self, i):
        return self._labels[i]

    def selectedRow(self):
        selected = self._selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=None):
        return len(self._labels)

    def columnCount(self, parent):
        return 3

    def _getToolTipSuffix(self, row):
        """
        Get the middle column tooltip suffix
        """
        suffix = "; Click to select"
        if row in self._toolTipSuffixes:
            suffix = self._toolTipSuffixes[row]
        return suffix

    def _setToolTipSuffix(self, row, text):
        """
        Set the middle column tooltip suffix
        """
        self._toolTipSuffixes[row] = text
        index = self.createIndex(row, 1)
        self.dataChanged.emit(index, index)

    class EntryToolTipAdapter(object):
        """This class can be used to make each row look like a
        separate widget with its own tooltip.

        In this case, the "tooltip" is the suffix appended to the
        tooltip of the middle column.

        """
        def __init__(self, table, row):
            self._row = row
            self._table = table
        def toolTip(self):
            return self._table._getToolTipSuffix(self._row)
        def setToolTip(self, text):
            self._table._setToolTipSuffix(self._row, text)

    def data(self, index, role):
        if role == Qt.EditRole and index.column() == ColumnID.Color:
            return (self._labels[index.row()].brushColor(),
                    self._labels[index.row()].pmapColor())

        if role == Qt.EditRole and index.column() == ColumnID.Name:
            return self._labels[index.row()].name

        if role == Qt.ToolTipRole and index.column() == ColumnID.Color:
            return ("Hex code : {}\nDouble click to change".format(
                self._labels[index.row()].brushColor().name()))

        if role == Qt.ToolTipRole and index.column() == ColumnID.Name:
            suffix = self._getToolTipSuffix(index.row())
            return "{}\nDouble click to rename {}".format(
                self._labels[index.row()].name, suffix)

        if role == Qt.ToolTipRole and index.column() == ColumnID.Delete:
            return "Delete {}".format(self._labels[index.row()].name)

        if role == Qt.DecorationRole and index.column() == ColumnID.Color:
            row = index.row()
            value = self._labels[row]
            if value.brushColor == value.pmapColor():
                pixmap = QPixmap(_NPIXELS, _NPIXELS)
                pixmap.fill(value.brushColor)
            else:
                a = value.brushColor().rgba()
                b = value.pmapColor().rgba()
                img = QImage(_NPIXELS,_NPIXELS, QImage.Format_RGB32)
                for i in range(_NPIXELS):
                    for j in range(0, _NPIXELS - i):
                        img.setPixel(i, j, a)
                for i in range(_NPIXELS):
                    for j in range(_NPIXELS - i, _NPIXELS):
                        img.setPixel(i, j, b)
                pixmap = QPixmap.fromImage(img)
            icon = QIcon(pixmap)
            return icon

        if role == Qt.DecorationRole and index.column() == ColumnID.Delete:
            row = index.row()
            pixmap = QPixmap(_NPIXELS, _NPIXELS)
            pixmap.fill(Qt.transparent)
            painter = QPainter()
            painter.begin(pixmap)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setBrush(QColor("red"))
            painter.drawEllipse(1, 1, _NPIXELS - 2, _NPIXELS - 2)
            pen = QPen(QColor("black"))
            pen.setWidth(2)
            painter.setPen(pen)

            x = _XSTART
            y = _NPIXELS - x
            painter.drawLine(x, x, y, y)
            painter.drawLine(y, x, x, y)

            painter.end()
            icon = QIcon(pixmap)
            return icon

        if role == Qt.DisplayRole and index.column() == ColumnID.Name:
            row = index.row()
            value = self._labels[row]
            return value.name

    def flags(self, index):
        if  index.column() == ColumnID.Color:
            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif  index.column() == ColumnID.Name:
            return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
        elif  index.column() == ColumnID.Delete:
            if self._allowRemove:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                return Qt.NoItemFlags

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole  and index.column() == ColumnID.Color:
            row = index.row()
            brushColor = QColor(value[0])
            pmapColor = QColor(value[1])
            if brushColor.isValid() and pmapColor.isValid():
                print "setData: brushColor = {}, pmapColor = {}".format(
                    brushColor.name(), pmapColor.name())
                print "  self._labels[row] has type {}".format(
                    type(self._labels[row]))
                self._labels[row].setBrushColor(brushColor)
                self._labels[row].setPmapColor(pmapColor)
                print "  self._labels[row].brushColor = {}".format(
                    self._labels[row].brushColor().name())
                print "  self._labels[row].pmapColor  = {}".format(
                    self._labels[row].pmapColor().name())
                self.dataChanged.emit(index, index)
                return True

        if role == Qt.EditRole  and index.column() == ColumnID.Name:
            row = index.row()
            name = value
            self._labels[row].name = str(name.toString())
            self.dataChanged.emit(index, index)
            return True

        return False

    def insertRow(self, position, object, parent=QModelIndex()):
        self.beginInsertRows(parent, position, position)
        self._labels.insert(position, object)
        self.endInsertRows()
        return True

    def removeRow(self, position, parent=QModelIndex()):
        self.beginRemoveRows(parent, position, position)
        value = self._labels[position]
        logger.debug("removing row: " + str(value))
        self._labels.remove(value)
        self.endRemoveRows()
        return True

    def allowRemove(self, check):
        #Allow removing of rows. Needed to be able to disallow it
        #in interactive mode
        self._allowRemove = check
        self.dataChanged.emit(self.createIndex(0, ColumnID.Delete),
                              self.createIndex(self.rowCount(), ColumnID.Delete))

    def select(self, row):
        self._selectionModel.clear()
        self._selectionModel.select(self.index(row, ColumnID.Color),
                                    QItemSelectionModel.Select)
        self._selectionModel.select(self.index(row, ColumnID.Name),
                                    QItemSelectionModel.Select)
Exemplo n.º 39
0
class MainWindow(QMainWindow, magazzino_ui.Ui_MainWindow):

    FIRST, PREV, NEXT, LAST = range(4)
    Clipboard = [] # lista di oggetti

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setupUi(self)
        self.setupMenu()
        self.restoreWinSettings()

        self.editindex = None
        self.filename = None
        self.db = QSqlDatabase.addDatabase("QSQLITE")

        self.loadInitialFile()
        self.setupUiSignals()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Down:
            self.addDettRecord()
        else:
            QMainWindow.keyPressEvent(self, event)

    def creaStrutturaDB(self):
        query = QSqlQuery()
        if not ("magamaster" in self.db.tables()):
            if not query.exec_("""CREATE TABLE magamaster (
                                id INTEGER PRIMARY KEY AUTOINCREMENT 
                                UNIQUE NOT NULL,
                                scaff VARCHAR(10) NOT NULL)"""):
                QMessageBox.warning(self, "Magazzino",
                                QString("Creazione tabella fallita!"))
                return False

        if not ("magaslave" in self.db.tables()):
            if not query.exec_("""CREATE TABLE magaslave (
                                id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
                                datains DATE NOT NULL,
                                abbi VARCHAR(50),
                                angro VARCHAR(50),
                                desc VARCHAR(100),
                                qt INTEGER NOT NULL DEFAULT '1',
                                imp DOUBLE NOT NULL DEFAULT '0.0',
                                equiv VARCHAR(100),
                                mmid INTEGER NOT NULL,
                                fatt VARCHAR(50),
                                note VARCHAR(200),
                                FOREIGN KEY (mmid) REFERENCES magamaster)"""):
                QMessageBox.warning(self, "Magazzino",
                                QString("Creazione tabella fallita!"))
                return False
            QMessageBox.information(self, "Magazzino",
                                QString("Database Creato!"))

        return True

    def loadFile(self, fname=None):
        if fname is None:
            return
        if self.db.isOpen():
            self.db.close()
        self.db.setDatabaseName(QString(fname))
        if not self.db.open():
            QMessageBox.warning(self, "Magazzino",
                                QString("Database Error: %1")
                                .arg(self.db.lastError().text()))
        else:
            if not self.creaStrutturaDB():
                return
            self.filename = unicode(fname)
            self.setWindowTitle("Gestione Magazzino - %s" % self.filename)
            self.setupModels()
            self.setupMappers()
            self.setupTables()
            #self.setupItmSignals()
            self.restoreTablesSettings()
            self.mmUpdate()


    def loadInitialFile(self):
        settings = QSettings()
        fname = unicode(settings.value("Settings/lastFile").toString())
        if fname and QFile.exists(fname):
            self.loadFile(fname)


    def openFile(self):
        dir = os.path.dirname(self.filename) \
                if self.filename is not None else "."
        fname = QFileDialog.getOpenFileName(self,
                    "Gestione Magazzino - Scegli database",
                    dir, "*.db")
        if fname:
            self.loadFile(fname)


    def newFile(self):
        dir = os.path.dirname(self.filename) \
                if self.filename is not None else "."
        fname = QFileDialog.getSaveFileName(self,
                    "Gestione Magazzino - Scegli database",
                    dir, "*.db")
        if fname:
            self.loadFile(fname)

    def setupMenu(self):
        # AboutBox
        self.connect(self.actionA_bout, SIGNAL("triggered()"),
                    self.showAboutBox)
        # FileNew
        self.connect(self.action_New_File, SIGNAL("triggered()"),
                    self.newFile)

        # FileLoad
        self.connect(self.action_Load_File, SIGNAL("triggered()"),
                    self.openFile)


    def showAboutBox(self):
        dlg = aboutmaga.AboutBox(self)
        dlg.exec_()


    def printInventory(self):
        '''
            Print Inventory
        '''
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        querygrp = QSqlQuery()
        querydett = QSqlQuery()

        querygrp.exec_("SELECT abbi,qt,imp,sum(qt*imp) "
                    "FROM magaslave GROUP BY abbi")
        querydett.prepare("SELECT datains,abbi,angro,desc,qt,imp "
                        "FROM magaslave WHERE abbi = :abbi AND "
                        "qt > 0 ORDER BY datains")

        from reportlab.pdfgen.canvas import Canvas
        from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
        from reportlab.lib.units import cm
        from reportlab.lib.enums import TA_LEFT,TA_RIGHT,TA_CENTER
        from reportlab.platypus import Spacer, SimpleDocTemplate 
        from reportlab.platypus import Table, TableStyle, Paragraph
        from reportlab.rl_config import defaultPageSize
        from reportlab.lib import colors

        PAGE_WIDTH, PAGE_HEIGHT=defaultPageSize
        styles = getSampleStyleSheet()
        styleN = styles['Normal']
        styleH = styles['Heading1']
        styleH.alignment=TA_CENTER
        Elements = []
        #add some flowables
        p=Paragraph
        ps=ParagraphStyle

        Title = unicode(self.prtTitleLineEdit.text())
        Year = unicode(self.prtDateLineEdit.text())
        Author = "Stefano Zamprogno"
        URL = "http://www.zamprogno.it/"
        email = "*****@*****.**"

        pageinfo = "%s / %s / %s" % (Author, email, Title)

        def myFirstPage(canvas, doc):
            canvas.saveState()
            canvas.setStrokeColorRGB(0.50,0.50,0.50)
            canvas.setLineWidth(10)
            canvas.line(45,72,45,PAGE_HEIGHT-72)
            #canvas.setFont('Times-Bold',16)
            #canvas.drawCentredString(3*cm, 1.5*cm,Title)
            canvas.setFont('Times-Roman',9)
            canvas.drawString(3*cm, 1.5*cm, "First Page / %s" % pageinfo)
            canvas.restoreState()

        def myLaterPages(canvas, doc):
            canvas.saveState()
            canvas.setStrokeColorRGB(0.50,0.50,0.50)
            canvas.setLineWidth(5)
            canvas.line(45,72,45,PAGE_HEIGHT-72)
            canvas.setFont('Times-Roman',9)
            canvas.drawString(3*cm, 1.5*cm, "Page %d %s" % (doc.page, pageinfo))
            canvas.restoreState()

        Elements.append(Paragraph(Title, styleH))
        Elements.append(Paragraph(Year,styleN))
        Elements.append(Spacer(0.5*cm, 0.5*cm))

        tot=0
        while querygrp.next():
            tot += querygrp.value(3).toDouble()[0]
            querydett.bindValue(":abbi", QVariant(querygrp.value(0).toString()))
            querydett.exec_()
            data = [['Abbi', 'Angro', 'Descrizione', 'Qt', 'Imp'],]
            while querydett.next():
                data.append([ p(unicode(querydett.value(1).toString()),
                                                ps(name='Normal')),
                                p(unicode(querydett.value(2).toString()),
                                                ps(name='Normal')),
                                p(unicode(querydett.value(3).toString()),
                                                ps(name='Normal')),
                                querydett.value(4).toInt()[0],
                                unicode("%.2f" %
                                        querydett.value(5).toDouble()[0])])
            data.append([None, None,
                        unicode("GRUPPO '%s'" % querygrp.value(0).toString()),
                        unicode("Subtotale:"),
                        unicode("€ %.2f" % querygrp.value(3).toDouble()[0])])
            Elements.append(Table(data,repeatRows=1,
                                style=(['LINEBELOW', (3,-2), (-1,-2),
                                            1, colors.black],
                                        ['LINEBELOW', (0,0), (-1,0),
                                            1, colors.black],
                                        ['ALIGN', (1,0), (3,-1),'CENTER'],
                                        ['ALIGN', (4,0), (-1,0),'RIGHT'],
                                        ['VALIGN', (0,0), (-1,-1), 'TOP'],
                                        ['ALIGN', (4,0), (-1,-1), 'RIGHT'],
#                                        ['TEXTCOLOR', (0,0), (-1,0),
#                                                colors.red],
                                        ['BACKGROUND',(0,0),(-1,0),
                                                colors.lightgrey],
                                        ['GRID',(0,0),(-1,-1), 0.2,
                                                colors.black],
                                        ['FONT', (0, 0), (-1, 0),
                                                'Helvetica-Bold', 10],
                                        ['FONT', (3, -1), (3, -1),
                                                'Helvetica-Bold', 10])))
            Elements.append(Spacer(0.5*cm, 0.5*cm))

        Elements.append(Paragraph("<para align=right><b>TOTALE GENERALE:"
                                    "€ %.2f</b></para>" % tot, styleN))

        doc = SimpleDocTemplate(os.path.join(os.path.dirname(__file__),
                        'mydoc.pdf'))
        doc.build(Elements,onFirstPage=myFirstPage, onLaterPages=myLaterPages)

        subprocess.Popen(['gnome-open',os.path.join(os.path.dirname(__file__),
                        'mydoc.pdf')])

    def setupMappers(self):
        '''
            Initialize all the application mappers
        '''
        self.mapper = QDataWidgetMapper(self)
        self.mapper.setModel(self.mModel)
        self.mapper.addMapping(self.scaffLineEdit, SCAFF)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.toFirst()

    def setupTables(self):
        """
            Initialize all the application tablesview
        """
        self.sTableView.setModel(self.sModel)
        self.sTableView.setItemDelegate(MSDelegate(self))
        self.sTableView.setColumnHidden(ID, True)
        self.sTableView.setColumnHidden(MMID, True)
        self.sTableView.setWordWrap(True)
        self.sTableView.resizeRowsToContents()
        self.sTableView.setAlternatingRowColors(True)
        self.sItmSelModel = QItemSelectionModel(self.sModel)
        self.sTableView.setSelectionModel(self.sItmSelModel)
        self.sTableView.setSelectionBehavior(QTableView.SelectRows)
        #self.sTableView.setTabKeyNavigation(True)


        self.fTableView.setModel(self.fModel)
        self.fTableView.setColumnHidden(ID, True)
        self.fTableView.setWordWrap(True)
        self.fTableView.resizeRowsToContents()
        self.fTableView.setAlternatingRowColors(True)
        self.fItmSelModel = QItemSelectionModel(self.fModel)
        self.fTableView.setSelectionModel(self.fItmSelModel)

    def setupModels(self):
        """
            Initialize all the application models
        """
        # setup slaveModel
        self.sModel = ssModel(self)
        self.sModel.setTable(QString("magaslave"))
        self.sModel.setHeaderData(ID, Qt.Horizontal, QVariant("ID"))
        self.sModel.setHeaderData(DATAINS, Qt.Horizontal, QVariant("DataIns"))
        self.sModel.setHeaderData(ABBI, Qt.Horizontal, QVariant("Abbi"))
        self.sModel.setHeaderData(ANGRO, Qt.Horizontal, QVariant("Angro"))
        self.sModel.setHeaderData(DESC, Qt.Horizontal, QVariant("Desc"))
        self.sModel.setHeaderData(QT, Qt.Horizontal, QVariant("Qt"))
        self.sModel.setHeaderData(IMP, Qt.Horizontal, QVariant("Imp"))
        self.sModel.setHeaderData(EQUIV, Qt.Horizontal, QVariant("Equiv"))
        self.sModel.setHeaderData(MMID, Qt.Horizontal, QVariant("ScaffId"))
        self.sModel.setHeaderData(FATT, Qt.Horizontal, QVariant("Fatt"))
        self.sModel.setHeaderData(NOTE, Qt.Horizontal, QVariant("Note"))
        self.sModel.setSort(DATAINS, Qt.AscendingOrder)
        self.sModel.setEditStrategy(QSqlTableModel.OnRowChange)
        self.sModel.select()

        # setup masterModel
        self.mModel = QSqlTableModel(self)
        self.mModel.setTable(QString("magamaster"))
        self.mModel.setSort(SCAFF, Qt.AscendingOrder)
        self.mModel.setHeaderData(ID, Qt.Horizontal, QVariant("ID"))
        self.mModel.setHeaderData(SCAFF, Qt.Horizontal, QVariant("Scaff"))
        self.mModel.select()

        # setup findModel
        self.fModel = QSqlRelationalTableModel(self)
        self.fModel.setTable(QString("magaslave"))
        self.fModel.setHeaderData(ID, Qt.Horizontal, QVariant("ID"))
        self.fModel.setHeaderData(DATAINS, Qt.Horizontal, QVariant("DataIns"))
        self.fModel.setHeaderData(ABBI, Qt.Horizontal, QVariant("Abbi"))
        self.fModel.setHeaderData(ANGRO, Qt.Horizontal, QVariant("Angro"))
        self.fModel.setHeaderData(DESC, Qt.Horizontal, QVariant("Desc"))
        self.fModel.setHeaderData(QT, Qt.Horizontal, QVariant("Qt"))
        self.fModel.setHeaderData(IMP, Qt.Horizontal, QVariant("Imp"))
        self.fModel.setHeaderData(EQUIV, Qt.Horizontal, QVariant("Equiv"))
        self.fModel.setHeaderData(MMID, Qt.Horizontal, QVariant("ScaffId"))
        self.fModel.setHeaderData(FATT, Qt.Horizontal, QVariant("Fatt"))
        self.fModel.setHeaderData(NOTE, Qt.Horizontal, QVariant("Note"))
        self.fModel.setSort(MMID, Qt.AscendingOrder)
        self.fModel.setRelation(MMID, QSqlRelation("magamaster",
                                            "id", "scaff"))
        self.fModel.select()

    def clipCopy(self):
        self.Clipboard = self.sTableView.selectedIndexes()
        selrows = self.sItmSelModel.selectedRows()
        # TODO : da usare:  selrows = self.sItmSelModel.selectedRows()
        print(selrows, len(selrows))
        print(len(self.Clipboard))
        # FIXME : bla bla bla

    def clipDel(self):
        self.delDettRecord()

    def clipPaste(self):
        pass

    def ctxtMenu(self, point):
        menu = QMenu(self)
        copyAction = menu.addAction("&Copy")
        self.connect(copyAction, SIGNAL("triggered()"), self.clipCopy)
        delAction = menu.addAction("&Del")
        self.connect(delAction, SIGNAL("triggered()"), self.clipDel)
        if len(self.Clipboard) > 0:
            pasteAction = menu.addAction("&Paste")
            self.connect(pasteAction, SIGNAL("triggered()"), self.clipPaste)

        menu.exec_(self.sTableView.mapToGlobal(point))


    def setupUiSignals(self):
        self.sTableView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.sTableView,  SIGNAL(
                        "customContextMenuRequested(const QPoint &)"),
                        self.ctxtMenu)
        self.connect(self.scaffLineEdit, SIGNAL("returnPressed()"),
                    lambda: self.saveRecord(MainWindow.FIRST))
        self.connect(self.findLineEdit, SIGNAL("returnPressed()"),
                    self.globalFilter)
        self.connect(self.printPushButton, SIGNAL("clicked()"),
                    self.printInventory)
        self.connect(self.createFilterPushButton, SIGNAL("clicked()"),
                    self.createFilter)
        self.connect(self.findPushButton, SIGNAL("clicked()"),
                    self.applyFilter)
        self.connect(self.gSearchPushButton, SIGNAL("clicked()"),
                    self.globalFilter)
        self.connect(self.addscaffPushButton, SIGNAL("clicked()"),
                    self.addScaffRecord)
        self.connect(self.adddettPushButton, SIGNAL("clicked()"),
                    self.addDettRecord)
        self.connect(self.deldettPushButton, SIGNAL("clicked()"),
                    self.delDettRecord)
        self.connect(self.delscaffPushButton, SIGNAL("clicked()"),
                    self.delScaffRecord)
        self.connect(self.scaffFirstPushButton, SIGNAL("clicked()"),
                    lambda: self.saveRecord(MainWindow.FIRST))
        self.connect(self.scaffPrevPushButton, SIGNAL("clicked()"),
                    lambda: self.saveRecord(MainWindow.PREV))
        self.connect(self.scaffNextPushButton, SIGNAL("clicked()"),
                    lambda: self.saveRecord(MainWindow.NEXT))
        self.connect(self.scaffLastPushButton, SIGNAL("clicked()"),
                    lambda: self.saveRecord(MainWindow.LAST))


    def globalFilter(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        txt = self.findLineEdit.text()
        qry =   ("(datains like '%s') OR "
                "(abbi like '%s') OR "
                "(angro like '%s') OR "
                "(desc like '%s') OR "
                "(equiv like '%s') OR"
                "(fatt like '%s') OR"
                "(note like '%s')") % ((txt,)*7)
        self.fModel.setFilter(qry)
        self.updateFilter()

    def updateFilter(self):
        self.fModel.select()
        self.fTableView.setColumnHidden(ID, True)

    def applyFilter(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        self.fModel.setFilter(self.findLineEdit.text())
        self.updateFilter()

    def createFilter(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        headerDef = ("datains VARCHAR(100)",
                            "abbi VARCHAR(100)",
                            "angro VARCHAR(100)",
                            "desc VARCHAR(100)",
                            "qt VARCHAR(100)",
                            "imp VARCHAR(100)",
                            "equiv VARCHAR(100)",
                            "fatt VARCHAR(100)",
                            "note VARCHAR(100)")
        dlg = filterdialog.FilterDialog(headerDef,
                        QSqlDatabase.database(), self)
        if(dlg.exec_()):
            self.findLineEdit.setText(dlg.filterDone() 
                                        if dlg.filterDone() else "")
            self.applyFilter()

    #~ def editEsc(self, idxcur, idxold):
        #~ if self.editindex and self.editindex.isValid():
            #~ if idxcur.row() != self.editindex.row():
                #~ self.sModel.revertAll()
                #~ self.editindex = None

    def mmUpdate(self):
        row = self.mapper.currentIndex()
        id = self.mModel.data(self.mModel.index(row,ID)).toString()
        self.sModel.setFilter("mmid=%s" % id)
        self.sModel.select()
        self.sTableView.setColumnHidden(ID, True)
        self.sTableView.setColumnHidden(MMID, True)

    def saveRecord(self, where):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        row = self.mapper.currentIndex()
        self.mapper.submit()
        self.sModel.revertAll()
        if where == MainWindow.FIRST:
            row=0
        elif where == MainWindow.PREV:
            row = 0 if row <= 1 else row - 1
        elif where == MainWindow.NEXT:
            row += 1
            if row >= self.mModel.rowCount():
                row = self.mModel.rowCount() -1
        elif where == MainWindow.LAST:
            row = self.mModel.rowCount()- 1
        self.mapper.setCurrentIndex(row)
        self.mmUpdate()

    def addScaffRecord(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        row = self.mModel.rowCount()
        self.mapper.submit()
        self.mModel.insertRow(row)
        self.mapper.setCurrentIndex(row)
        self.scaffLineEdit.setFocus()
        self.mmUpdate()

    def addDettRecord(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        rowscaff = self.mapper.currentIndex()
        record = self.mModel.record(rowscaff)
        masterid = record.value(ID).toInt()[0]
        if masterid < 1:
            self.statusbar.showMessage(
                "Scaffale non valido o non confermato...",
                5000)
            self.scaffLineEdit.setFocus()
            return
        # aggiunge la nuova riga alla vista
        self.sModel.submitAll()
        self.sModel.select()
        row = self.sModel.rowCount()
        self.sModel.insertRow(row)
        if row > 1:
            precfatt = self.sModel.data(self.sModel.index(row-1, FATT))
        else:
            precfatt = ''
        if row > 1:
            lastData = self.sModel.data(self.sModel.index(row-1, DATAINS))
        else:
            lastData = ''
        self.sModel.setData(self.sModel.index(row, MMID),
                                                QVariant(masterid))
        self.sModel.setData(self.sModel.index(row, QT),
                                                QVariant(1))
        self.sModel.setData(self.sModel.index(row, IMP),
                                                QVariant(0.0))
        self.sModel.setData(self.sModel.index(row, FATT),
                                                QVariant(precfatt))
        self.editindex = self.sModel.index(row, DATAINS)
        self.sTableView.setCurrentIndex(self.editindex)
        self.sTableView.edit(self.editindex)

    def delDettRecord(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        selrows = self.sItmSelModel.selectedRows()
        if not selrows:
            self.statusbar.showMessage(
                "No articles selected to delete...",
                5000)
            return
        if(QMessageBox.question(self, "Cancella Articoli",
                "Vuoi cancellare: {0} articoli?".format(len(selrows)),
                QMessageBox.Yes|QMessageBox.No) ==
                QMessageBox.No):
            return
        QSqlDatabase.database().transaction()
        query = QSqlQuery()
        query.prepare("DELETE FROM magaslave WHERE id = :val")
        for i in selrows:
            if i.isValid():
                query.bindValue(":val", QVariant(i.data().toInt()[0]))
                query.exec_()
        QSqlDatabase.database().commit()
        self.sModel.revertAll()
        self.mmUpdate()

    def delScaffRecord(self):
        if not self.db.isOpen():
            self.statusbar.showMessage(
                "Database non aperto...",
                5000)
            return
        row = self.mapper.currentIndex()
        if row == -1:
            self.statusbar.showMessage(
                        "Nulla da cancellare...",
                        5000)
            return
        record = self.mModel.record(row)
        id = record.value(ID).toInt()[0]
        scaff = record.value(SCAFF).toString()
        if(QMessageBox.question(self, "Cancella Scaffale",
                    "Vuoi cancellare lo scaffale: {0} ?".format(scaff),
                    QMessageBox.Yes|QMessageBox.No) ==
                    QMessageBox.No):
            self.statusbar.showMessage(
                        "Cancellazione scaffale annullata...",
                        5000)
            return
        # cancella scaffale
        self.mModel.removeRow(row)
        self.mModel.submitAll()
        if row + 1 >= self.mModel.rowCount():
            row = self.mModel.rowCount() - 1
        self.mapper.setCurrentIndex(row)
        if self.mModel.rowCount() == 0:
            self.scaffLineEdit.setText(QString(""))

        # cancella tutti gli articoli che si riferiscono
        # allo scaffale cancellato
        self.sModel.setFilter("mmid=%s" % id)
        self.sModel.select()
        self.sModel.removeRows(0, self.sModel.rowCount())
        self.sModel.submitAll()
        self.statusbar.showMessage(
                        "Cancellazione eseguita...",
                        5000)
        self.mmUpdate()

    def restoreTablesSettings(self):
        settings = QSettings(self)
        if self.saveTableGeometryCheckBox.isChecked():
            # per la tabella slave
            for c in range(1, self.sModel.columnCount()-1):
                width = settings.value("Settings/sTableView/%s" % c,
                                        QVariant(60)).toInt()[0]
                self.sTableView.setColumnWidth(c,
                                            width if width > 0 else 60)

            # per la tabella find
            for c in range(1, self.fModel.columnCount()):
                width = settings.value("Settings/fTableView/%s" % c,
                                        QVariant(60)).toInt()[0]
                self.fTableView.setColumnWidth(c,
                                            width if width > 0 else 60)

    def restoreWinSettings(self):
        settings = QSettings()
        self.prtTitleLineEdit.setText(QString(settings.value(
                            "Settings/printTitle", QVariant(
                            "Situazione Magazzino - TIME di Stefano Zamprogno")).toString()))
        self.prtDateLineEdit.setText(QString(settings.value(
                            "Settings/printDate", QVariant(
                            "Al 31/12/2008")).toString()))
        self.saveWinPosCheckBox.setChecked(
                settings.value("Settings/saveWinPos", QVariant(True)).toBool())
        self.saveTableGeometryCheckBox.setChecked(
                settings.value("Settings/saveTableGeometry",
                QVariant(True)).toBool())
        self.restoreGeometry(
                settings.value("MainWindow/Geometry").toByteArray())

    def closeEvent(self, event):
        settings = QSettings()
        if self.filename is not None:
            settings.setValue("Settings/lastFile", QVariant(self.filename))
        settings.setValue("MainWindow/Geometry", QVariant(
                          self.saveGeometry()))
        settings.setValue("Settings/saveWinPos", QVariant(
                          self.saveWinPosCheckBox.isChecked()))
        settings.setValue("Settings/saveTableGeometry", QVariant(
                          self.saveTableGeometryCheckBox.isChecked()))
        settings.setValue("Settings/printTitle", QVariant(
                          self.prtTitleLineEdit.text()))
        settings.setValue("Settings/printDate", QVariant(
                          self.prtDateLineEdit.text()))

        if self.db.isOpen():
            # salva larghezza colonne tabella slave
            for c in range(1, self.sModel.columnCount()-1):
                width = self.sTableView.columnWidth(c)
                if width:
                    settings.setValue("Settings/sTableView/%s" % c,
                                        QVariant(width))

            # salva larghezza colonne tabella find
            for c in range(1, self.fModel.columnCount()):
                width = self.fTableView.columnWidth(c)
                if width:
                    settings.setValue("Settings/fTableView/%s" % c,
                        QVariant(width))
        self.db.close()
        del self.db
Exemplo n.º 40
0
 def __init__(self, model, parent=None):
     QItemSelectionModel.__init__(self, model, parent)
     self.selectionChanged.connect(self.onSelectionChanged)
Exemplo n.º 41
0
class ListModel(QAbstractTableModel):
    orderChanged = pyqtSignal()
    elementSelected = pyqtSignal(int)


    class ColumnID():
        '''
        Define how many column the model holds and their type

        '''
        ncols=2
        Name=0
        Delete=1

    def __init__(self, elements=None, parent=None):
        '''
        Common interface for the labelListModel and the boxListModel
        see concrete implementations for details

        :param elements:
        :param parent:
        '''
        QAbstractTableModel.__init__(self, parent)

        if elements is None:
            elements = []
        self._elements = list(elements)
        self._selectionModel = QItemSelectionModel(self)

        def onSelectionChanged(selected, deselected):


            if selected:
                ind = selected[0].indexes()
                if len(ind)>0:
                    self.elementSelected.emit(ind[0].row())

        self._selectionModel.selectionChanged.connect(onSelectionChanged)

        self._allowRemove = True
        self._toolTipSuffixes = {}

        self.unremovable_rows=[] #rows in this list cannot be removed from the gui,
                                 # to add to this list call self.makeRowPermanent(int)
                                 # to remove make the self.makeRowRemovable(int)
    def makeRowPermanent(self,rowindex):
        """
        The rowindex cannot be removed from gui
        to remove this index use self.makeRowRemovable
        """

        self.unremovable_rows.append(rowindex)

    def makeRowRemovable(self,rowindex):
        self.unremovable_rows.pop(rowindex)

    def __len__(self):
        return len(self._elements)

    def __getitem__(self, i):
        return self._elements[i]

    def selectedRow(self):
        selected = self._selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1

    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()

    def rowCount(self, parent=None):
        return len(self._elements)

    def columnCount(self, parent):
        return self.ColumnID.ncols

    def _getToolTipSuffix(self, row):
        """
        Get the middle column tooltip suffix
        """
        suffix = "; Click to select"
        if row in self._toolTipSuffixes:
            suffix = self._toolTipSuffixes[row]
        return suffix

    def _setToolTipSuffix(self, row, text):
        """
        Set the middle column tooltip suffix
        """
        self._toolTipSuffixes[row] = text
        index = self.createIndex(row, 1)
        self.dataChanged.emit(index, index)

    class EntryToolTipAdapter(object):
        """This class can be used to make each row look like a
        separate widget with its own tooltip.

        In this case, the "tooltip" is the suffix appended to the
        tooltip of the middle column.

        """
        def __init__(self, table, row):
            self._row = row
            self._table = table
        def toolTip(self):
            return self._table._getToolTipSuffix(self._row)
        def setToolTip(self, text):
            self._table._setToolTipSuffix(self._row, text)



    def insertRow(self, position, object, parent=QModelIndex()):
        self.beginInsertRows(parent, position, position)
        object.changed.connect(self.modelReset)
        self._elements.insert(position, object)
        self.endInsertRows()
        return True

    def removeRow(self, position, parent=QModelIndex()):
        if position in self.unremovable_rows:
            return False

        self.beginRemoveRows(parent, position, position)
        value = self._elements[position]
        logger.debug("removing row: " + str(value))
        self._elements.remove(value)
        self.endRemoveRows()
        return True

    def allowRemove(self, check):
        #Allow removing of rows. Needed to be able to disallow it
        #in interactive mode
        self._allowRemove = check
        self.dataChanged.emit(self.createIndex(0, self.ColumnID.Delete),
                              self.createIndex(self.rowCount(), self.ColumnID.Delete))
    def data(self, index, role):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param index:
        :param role:
        '''

        if role == Qt.EditRole and index.column() == self.ColumnID.Name:
            return self._elements[index.row()].name


        elif role == Qt.ToolTipRole and index.column() == self.ColumnID.Delete:
            return "Delete {}".format(self._elements[index.row()].name)

        elif role == Qt.ToolTipRole and index.column() == self.ColumnID.Name:
            suffix = self._getToolTipSuffix(index.row())
            return "{}\nDouble click to rename {}".format(
                self._elements[index.row()].name, suffix)
        elif role == Qt.DisplayRole and index.column() == self.ColumnID.Name:
            row = index.row()
            value = self._elements[row]
            return value.name


        if role == Qt.DecorationRole and index.column() == self.ColumnID.Delete:
            if index.row() in self.unremovable_rows: return

            row = index.row()
            pixmap = QPixmap(_NPIXELS, _NPIXELS)
            pixmap.fill(Qt.transparent)
            painter = QPainter()
            painter.begin(pixmap)
            painter.setRenderHint(QPainter.Antialiasing)
            painter.setBrush(QColor("red"))
            painter.drawEllipse(1, 1, _NPIXELS - 2, _NPIXELS - 2)
            pen = QPen(QColor("black"))
            pen.setWidth(2)
            painter.setPen(pen)

            x = _XSTART
            y = _NPIXELS - x
            painter.drawLine(x, x, y, y)
            painter.drawLine(y, x, x, y)

            painter.end()
            icon = QIcon(pixmap)
            return icon

    def flags(self, index):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param index:
        '''
        if index.column() == self.ColumnID.Delete:
            if self._allowRemove:
                return Qt.ItemIsEnabled | Qt.ItemIsSelectable
            else:
                return Qt.NoItemFlags
        elif  index.column() == self.ColumnID.Name:
            return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def setData(self, index, value, role=Qt.EditRole):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param index:
        '''
        if role == Qt.EditRole  and index.column() == self.ColumnID.Name:
            row = index.row()
            name = value
            self._elements[row].name = str(name.toString())
            self.dataChanged.emit(index, index)
            return True

        return False

    def select(self, row):
        '''
        Reimplement, see labelListModel or boxListModel for concrete example
        :param row
        '''
        self._selectionModel.clear()
        self._selectionModel.select(self.index(row, self.ColumnID.Name),
                                    QItemSelectionModel.Select)

    def clearSelectionModel(self):
        self._selectionModel.clear()
Exemplo n.º 42
0
class ConfigDBSelector(QDialog, Ui_Dialog):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent=None, aptinkerQSettings=None):
        """Constructor"""

        QDialog.__init__(self, parent=parent)

        self.setupUi(self)

        self.setWindowFlags(Qt.Window) # To add Maximize & Minimize buttons
        self.setWindowTitle('Select Configuration from Database')

        # Load Startup Preferences for Config Table
        self.default_config_pref = dict(
            vis_col_key_list=config.DEF_VIS_COL_KEYS['config_setup'][:])
        if osp.exists(PREF_CONFIG_JSON_FILEPATH):
            with open(PREF_CONFIG_JSON_FILEPATH, 'r') as f:
                self.config_pref = json.load(f)
        else:
            self.config_pref = self.default_config_pref

        # Load Startup Preferences for Config Meta Table
        self.default_config_meta_pref = dict(
            vis_col_key_list=['config_id', 'config_ctime', 'config_name',
                              'username', 'config_ref_step_size',
                              'config_masar_id'])
        if osp.exists(PREF_CONFIG_META_JSON_FILEPATH):
            with open(PREF_CONFIG_META_JSON_FILEPATH, 'r') as f:
                self.config_meta_pref = json.load(f)
        else:
            self.config_meta_pref = self.default_config_meta_pref

        self.configDBViewWidget = ConfigDBViewWidget(
            self.groupBox_selected_conf)
        self.tableView_config = self.configDBViewWidget.tableView

        self.configMetaDBViewWidget = ConfigMetaDBViewWidget(
            self.groupBox_search_result)
        self.tableView_config_meta = self.configMetaDBViewWidget.tableView
        self.textEdit_description = \
            self.configMetaDBViewWidget.textEdit_description

        self.settings = QSettings('APHLA', 'TinkerConfigDBSelector')
        self.loadViewSettings()

        self._aptinkerQSettings = aptinkerQSettings

        self.pushButton_search.setIcon(QIcon(':/search.png'))

        all_ctime_operators = [
            self.comboBox_time_created_1.itemText(i)
            for i in range(self.comboBox_time_created_1.count())]
        self.comboBox_time_created_1.setCurrentIndex(
            all_ctime_operators.index(''))
        self.dateTimeEdit_time_created_1.setDateTime(
            QDateTime.currentDateTime())
        self.dateTimeEdit_time_created_2.setDateTime(
            QDateTime.currentDateTime())

        self.search_params = dict(
            config_id_1='', config_id_2='',
            ref_step_size_1='', ref_step_size_2='',
            config_name='', config_desc='', username='',
            ctime_1='', ctime_2='',
            synced_gruop_weight='',
            masar_id_1='', masar_id_2='')

        db_id_validator = QIntValidator()
        db_id_validator.setBottom(1)
        self.lineEdit_config_id_1.setValidator(db_id_validator)
        self.lineEdit_config_id_2.setValidator(db_id_validator)
        self.lineEdit_masar_id_1.setValidator(db_id_validator)
        self.lineEdit_masar_id_2.setValidator(db_id_validator)

        self.prev_valid_ref_step_sizes = dict(
            lineEdit_ref_step_size_1=np.nan, lineEdit_ref_step_size_2=np.nan)

        # Set up Config Table
        self.config_model = ConfigModel()
        self.tableModel_config = self.config_model.table
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_config)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_config
        tbV.setModel(proxyModel)
        tbV.setItemDelegate(ConfigDBTableViewItemDelegate(
            tbV, self.tableModel_config, tbV.parent()))

        self.db = self.config_model.db
        if '[config_meta_table text view]' not in self.db.getViewNames(
            square_brackets=True):
            self.db.create_temp_config_meta_table_text_view()

        # Set up Config Meta Table
        self.config_meta_all_col_keys = self.configMetaDBViewWidget.all_col_keys
        self.search_result = {k: [] for k in self.config_meta_all_col_keys}

        self.tableModel_config_meta = MetaTableModel(
            self.search_result, self.configMetaDBViewWidget)
        proxyModel = QSortFilterProxyModel()
        proxyModel.setSourceModel(self.tableModel_config_meta)
        proxyModel.setDynamicSortFilter(False)
        tbV = self.tableView_config_meta
        tbV.setModel(proxyModel)
        self.selectionModel = QItemSelectionModel(proxyModel)
        tbV.setSelectionModel(self.selectionModel)

        # Apply Visible Column Preference to Config Table
        (col_keys, col_names) = config.COL_DEF.getColumnDataFromTable(
            'column_table',
            column_name_list=['column_key','short_descrip_name'],
            condition_str='column_key in ({0:s})'.format(
                ','.join(['"{0:s}"'.format(k)
                          for k in self.config_pref['vis_col_key_list']]
                         )
            )
        )
        config_vis_col_name_list = [
            col_names[col_keys.index(k)]
            for k in self.config_pref['vis_col_key_list']]
        self.configDBViewWidget.on_column_selection_change(
            config_vis_col_name_list, force_visibility_update=True)

        # Apply Visible Column Preference to Config Meta Table
        config_meta_vis_col_name_list = [
            self.configMetaDBViewWidget.col_names_wo_desc[
                self.configMetaDBViewWidget.col_keys_wo_desc.index(k)]
            for k in self.config_meta_pref['vis_col_key_list']]
        self.configMetaDBViewWidget.on_column_selection_change(
            config_meta_vis_col_name_list, force_visibility_update=True)

        # Make connection

        self.connect(self.lineEdit_ref_step_size_1, SIGNAL('editingFinished()'),
                     self.validate_ref_step_size)
        self.connect(self.lineEdit_ref_step_size_2, SIGNAL('editingFinished()'),
                     self.validate_ref_step_size)

        self.connect(self.pushButton_search, SIGNAL('clicked()'),
                     self.update_search)

        self.connect(
            self.selectionModel,
            SIGNAL(
                'currentRowChanged(const QModelIndex &, const QModelIndex &)'),
            self.on_selection_change
        )

        self.connect(self.configMetaDBViewWidget, SIGNAL('exportConfigToFile'),
                     self.exportConfigToFile)
        self.connect(self.configMetaDBViewWidget,
                     SIGNAL('editConfigNameOrDescription'),
                     self.editConfigNameOrDescription)

    #----------------------------------------------------------------------
    def exportConfigToFile(self):
        """"""

        msg = QMessageBox()

        inds = self.selectionModel.selectedRows()

        if inds != []:
            row = inds[0].row()
            config_id = self.search_result['config_id'][row]
            saved_filepath = self.config_model.abstract.exportToFile(
                config_id, self._aptinkerQSettings)
            if saved_filepath:
                msg.setText(
                    'Successfully exported config (ID={0:d}) to the file "{1}".'.
                    format(config_id, saved_filepath))
                msg.exec_()
        else:
            msg.setText('You must select a configuration to be exported.')
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()

    #----------------------------------------------------------------------
    def editConfigNameOrDescription(self):
        """"""

        msg = QMessageBox()

        inds = self.selectionModel.selectedRows()

        if inds != []:
            row = inds[0].row()
            config_id = self.search_result['config_id'][row]

            title = 'Edit Config Name or Description'
            prompt = 'Property to Edit:'
            result = QInputDialog.getItem(
                self, title, prompt, ['Name', 'Description'], current=1,
                editable=False)

            if result[1]:
                table_name = 'config_meta_text_search_table'
                if result[0] == 'Name':
                    current_name, current_desc = self.db.getColumnDataFromTable(
                        table_name, column_name_list=['config_name',
                                                      'config_description'],
                        condition_str='config_id={0:d}'.format(config_id))
                    current_name = current_name[0]
                    current_desc = current_desc[0]

                    title = 'Edit Config Name'
                    prompt = 'Enter a new name:'
                    result = QInputDialog.getText(self, title, prompt,
                                                  text=current_name)

                    if result[1]:
                        new_name = result[0]

                        mod_time_str = datestr(time.time())
                        new_desc = current_desc + (
                            ('\n### Modified by "{0}" on {1}###\n  Config Name '
                             'changed from "{2}" to "{3}"\n').format(
                                 getusername(), mod_time_str, current_name,
                                 new_name))

                        self.db.changeValues(
                            table_name, 'config_name',
                            '"{0}"'.format(new_name.replace('"', '""')),
                            condition_str='config_id={0:d}'.format(config_id))
                        self.db.changeValues(
                            table_name, 'config_description',
                            '"{0}"'.format(new_desc.replace('"', '""')),
                            condition_str='config_id={0:d}'.format(config_id))

                        # Update Config Meta DB Table
                        row = self.search_result['config_id'].index(config_id)
                        self.search_result['config_name'][row] = new_name
                        self.search_result['config_description'][row] = new_desc
                        self.tableModel_config_meta.repaint()
                        self.on_selection_change(None, None)

                else:
                    current_desc, = self.db.getColumnDataFromTable(
                        table_name, column_name_list=['config_description'],
                        condition_str='config_id={0:d}'.format(config_id))
                    current_desc = current_desc[0]

                    dialog = ConfigDescriptionEditor(current_desc, parent=self)
                    dialog.exec_()

                    if dialog.result() == QDialog.Accepted:
                        mod_time_str = datestr(time.time())
                        temp_new_desc = dialog.plainTextEdit_new.property(
                            'plainText')

                        new_desc = current_desc + (
                            ('\n### Modified by "{0}" on {1}###\n{2}\n'.format(
                            getusername(), mod_time_str, temp_new_desc))
                        )

                        self.db.changeValues(
                            table_name, 'config_description',
                            '"{0}"'.format(new_desc.replace('"', '""')),
                            condition_str='config_id={0:d}'.format(config_id))

                        # Update Config Meta DB Table
                        row = self.search_result['config_id'].index(config_id)
                        self.search_result['config_description'][row] = new_desc
                        self.tableModel_config_meta.repaint()
                        self.on_selection_change(None, None)

        else:
            msg.setText('You must select a configuration whose name or '
                        'description to be edited.')
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()

    #----------------------------------------------------------------------
    def closeEvent(self, event):
        """"""

        self.saveViewSettings()

        self.config_model.abstract.channel_ids = []

        event.accept()

    #----------------------------------------------------------------------
    def accept(self):
        """"""

        a = self.config_model.abstract

        if not a.isDataValid():
            return

        if not a.check_aphla_unitconv_updates():
            return

        self.saveViewSettings()

        super(ConfigDBSelector, self).accept() # will close the dialog

    #----------------------------------------------------------------------
    def reject(self):
        """"""

        self.config_model.abstract.channel_ids = []

        self.saveViewSettings()

        super(ConfigDBSelector, self).reject() # will close the dialog

    #----------------------------------------------------------------------
    def loadViewSettings(self):
        """"""

        self.settings.beginGroup('viewSize')

        rect = self.settings.value('position')
        if not rect:
            rect = QRect(0, 0, self.sizeHint().width(), self.sizeHint().height())
        self.setGeometry(rect)

        splitter_sizes = self.settings.value('splitter_1')
        if splitter_sizes is None:
            splitter_sizes = [self.width()*(1./2), self.width()*(1./2)]
        else:
            splitter_sizes = [int(s) for s in splitter_sizes]
        self.splitter.setSizes(splitter_sizes)

        splitter_sizes = self.settings.value('splitter_2')
        if splitter_sizes is None:
            splitter_sizes = [self.width()*(1./5), self.width()*(4./5)]
        else:
            splitter_sizes = [int(s) for s in splitter_sizes]
        self.splitter_2.setSizes(splitter_sizes)

        splitter_sizes = self.settings.value('splitter_3')
        if splitter_sizes is None:
            splitter_sizes = [self.configMetaDBViewWidget.height()*(2./3),
                              self.configMetaDBViewWidget.height()*(1./3)]
        else:
            splitter_sizes = [int(s) for s in splitter_sizes]
        self.configMetaDBViewWidget.splitter.setSizes(splitter_sizes)

        self.settings.endGroup()

    #----------------------------------------------------------------------
    def saveViewSettings(self):
        """"""

        self.settings.beginGroup('viewSize')

        self.settings.setValue('position', self.geometry())

        self.settings.setValue('splitter_1', self.splitter.sizes())
        self.settings.setValue('splitter_2', self.splitter_2.sizes())
        self.settings.setValue('splitter_3',
                               self.configMetaDBViewWidget.splitter.sizes())

        self.settings.endGroup()

    #----------------------------------------------------------------------
    def validate_ref_step_size(self):
        """"""

        sender = self.sender()
        name = sender.objectName()
        text = sender.text().strip()
        if text == '':
            text = 'nan'

        try:
            new_float = float(text)
            if np.isnan(new_float):
                sender.setText('')
            self.prev_valid_ref_step_sizes[name] = new_float
        except:
            msg = QMessageBox()
            msg.setText('Invalid float string: {0:s}'.format(text))
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()
            if np.isnan(self.prev_valid_ref_step_sizes[name]):
                sender.setText('')
            else:
                sender.setText(str(self.prev_valid_ref_step_sizes[name]))

    #----------------------------------------------------------------------
    def update_search(self):
        """"""

        try:
            config_id_1_text = str(int(self.lineEdit_config_id_1.text()))
        except:
            config_id_1_text = ''
        try:
            config_id_2_text = str(int(self.lineEdit_config_id_2.text()))
        except:
            config_id_2_text = ''
        config_id_1_operator = \
            self.comboBox_config_id_1.currentText().strip()
        config_id_2_operator = \
            self.comboBox_config_id_2.currentText().strip()
        if (config_id_1_text != '') and (config_id_1_operator != ''):
            self.search_params['config_id_1'] = (
                'config_id {0:s} {1:s}'.format(config_id_1_operator,
                                               config_id_1_text))
        else:
            self.search_params['config_id_1'] = ''
        if (config_id_2_text != '') and (config_id_2_operator != ''):
            self.search_params['config_id_2'] = (
                'config_id {0:s} {1:s}'.format(config_id_2_operator,
                                               config_id_2_text))
        else:
            self.search_params['config_id_2'] = ''

        try:
            masar_id_1_text = str(int(self.lineEdit_masar_id_1.text()))
        except:
            masar_id_1_text = ''
        try:
            masar_id_2_text = str(int(self.lineEdit_masar_id_2.text()))
        except:
            masar_id_2_text = ''
        masar_id_1_operator = \
            self.comboBox_masar_id_1.currentText().strip()
        masar_id_2_operator = \
            self.comboBox_masar_id_2.currentText().strip()
        if (masar_id_1_text != '') and (masar_id_1_operator != ''):
            self.search_params['masar_id_1'] = (
                'config_masar_id {0:s} {1:s}'.format(masar_id_1_operator,
                                                     masar_id_1_text))
        else:
            self.search_params['masar_id_1'] = ''
        if (masar_id_2_text != '') and (masar_id_2_operator != ''):
            self.search_params['masar_id_2'] = (
                'config_masar_id {0:s} {1:s}'.format(masar_id_2_operator,
                                                     masar_id_2_text))
        else:
            self.search_params['masar_id_2'] = ''

        try:
            ref_step_size_1_text = '{0:.9e}'.format(
                float(self.lineEdit_ref_step_size_1.text()))
        except:
            ref_step_size_1_text = ''
        try:
            ref_step_size_2_text = '{0:.9e}'.format(
                float(self.lineEdit_ref_step_size_2.text()))
        except:
            ref_step_size_2_text = ''
        ref_step_size_1_operator = \
            self.comboBox_ref_step_size_1.currentText().strip()
        ref_step_size_2_operator = \
            self.comboBox_ref_step_size_2.currentText().strip()
        if (ref_step_size_1_text != '') and (ref_step_size_1_operator != ''):
            self.search_params['ref_step_size_1'] = (
                'config_ref_step_size {0:s} {1:s}'.format(
                    ref_step_size_1_operator, ref_step_size_1_text))
        else:
            self.search_params['ref_step_size_1'] = ''
        if (ref_step_size_2_text != '') and (ref_step_size_2_operator != ''):
            self.search_params['ref_step_size_2'] = (
                'config_ref_step_size {0:s} {1:s}'.format(
                    ref_step_size_2_operator, ref_step_size_2_text))
        else:
            self.search_params['ref_step_size_2'] = ''

        synced_group_weight_text = \
            self.comboBox_synced_group_weight.currentText()
        if synced_group_weight_text == 'False':
            self.search_params['synced_group_weight'] = \
                'config_synced_group_weight = 0'
        elif synced_group_weight_text == 'True':
            self.search_params['synced_group_weight'] = \
                'config_synced_group_weight = 1'
        else:
            self.search_params['synced_group_weight'] = ''

        config_name_text = self.lineEdit_config_name.text().strip()
        if config_name_text != '':
            cond_str = self.db.get_MATCH_condition_str(config_name_text)
            if cond_str is not None:
                try:
                    self.search_params['config_name'] = \
                        self.db.get_config_ids_with_MATCH(cond_str, 'config_name')
                except:
                    msg = QMessageBox()
                    msg.setText('Invalid search strings for "Config Name"')
                    msg.setInformativeText(sys.exc_info()[1].__repr__())
                    msg.setIcon(QMessageBox.Critical)
                    msg.exec_()
                    return
            else:
                return
        else:
            self.search_params['config_name'] = []

        config_desc_text = self.lineEdit_config_description.text().strip()
        if config_desc_text != '':
            cond_str = self.db.get_MATCH_condition_str(config_desc_text)
            if cond_str is not None:
                try:
                    self.search_params['config_description'] = \
                        self.db.get_config_ids_with_MATCH(cond_str, 'config_description')
                except:
                    msg = QMessageBox()
                    msg.setText('Invalid search strings for "Config Description"')
                    msg.setInformativeText(sys.exc_info()[1].__repr__())
                    msg.setIcon(QMessageBox.Critical)
                    msg.exec_()
                    return
            else:
                return
        else:
            self.search_params['config_description'] = []

        username_text = self.lineEdit_username.text().strip()
        if username_text != '':
            self.search_params['username'] = \
                self.db.get_GLOB_condition_str(username_text, 'username')
        else:
            self.search_params['username'] = ''

        ctime_1_operator = self.comboBox_time_created_1.currentText().strip()
        if ctime_1_operator != '':
            ctime_epoch_1 = self.dateTimeEdit_time_created_1.dateTime()
            ctime_epoch_1 = time.mktime(ctime_epoch_1.toPyDateTime().timetuple())
            self.search_params['ctime_1'] = (
                'config_ctime {0:s} {1:.3f}'.format(ctime_1_operator, ctime_epoch_1))
        else:
            self.search_params['ctime_1'] = ''
        ctime_2_operator = self.comboBox_time_created_2.currentText().strip()
        if ctime_2_operator != '':
            ctime_epoch_2 = self.dateTimeEdit_time_created_2.dateTime()
            ctime_epoch_2 = time.mktime(ctime_epoch_2.toPyDateTime().timetuple())
            self.search_params['ctime_2'] = (
                'config_ctime {0:s} {1:.3f}'.format(ctime_2_operator, ctime_epoch_2))
        else:
            self.search_params['ctime_2'] = ''

        if (self.search_params['config_name'] is None) or \
           (self.search_params['config_description'] is None):
            for k in self.config_meta_all_col_keys:
                self.search_result[k] = []
        else:
            condition_str = ''
            for k, v in self.search_params.iteritems():
                if k in ('config_name', 'config_description'):
                    if v:
                        if condition_str != '':
                            condition_str += ' AND '
                        condition_str += '(config_id IN ({0:s}))'.format(
                            ','.join([str(i) for i in v]))
                else:
                    if v:
                        if condition_str != '':
                            condition_str += ' AND '
                        condition_str += '({0:s})'.format(v)
            out = self.db.getColumnDataFromTable(
                '[config_meta_table text view]',
                column_name_list=self.config_meta_all_col_keys,
                condition_str=condition_str, order_by_str='config_id')
            if out != []:
                if self.checkBox_hide_NG.isChecked():
                    config_name_col_ind = self.config_meta_all_col_keys.index(
                        'config_name')
                    valid_indexes = [
                        i for i, name in enumerate(out[config_name_col_ind])
                        if '$NG$' not in name]
                else:
                    valid_indexes = range(len(out[0]))
                for k, v in zip(self.config_meta_all_col_keys, out):
                    self.search_result[k] = [x for i, x in enumerate(v)
                                             if i in valid_indexes]
            else:
                for k in self.config_meta_all_col_keys:
                    self.search_result[k] = []

        self.tableModel_config_meta.repaint()

        self.on_selection_change(None, None)

    #----------------------------------------------------------------------
    def convert_GLOB_to_LIKE_wildcards(self, char):
        """"""

        if char == '*':
            return '%'
        elif char == '?':
            return '_'
        else:
            raise ValueError('Unexpected char: {0:s}'.format(char))

    #----------------------------------------------------------------------
    def get_LIKE_condition_str(self, glob_pattern, column_name):
        """"""

        backslahs_inds = [i for i, c in enumerate(glob_pattern) if c == '\\']
        like_pattern = ''.join(
            [self.convert_GLOB_to_LIKE_wildcards(c)
             if (c in ('*','?')) and (i-1 not in backslahs_inds) else c
             for i, c in enumerate(glob_pattern)])
        cond_str = '({0:s} LIKE "{1:s}" ESCAPE "\\")'.format(column_name,
                                                             like_pattern)

        return cond_str

    #----------------------------------------------------------------------
    def on_selection_change(self, current_index, previous_index):
        """"""

        a = self.config_model.abstract

        if current_index is None:
            self.textEdit_description.setText('')
            a.ref_step_size = np.nan
            (a.group_name_ids, a.channel_ids, a.weights,
             a.caput_enabled_rows) = [], [], [], []
        else:
            row = current_index.row()

            a.config_id    = self.search_result['config_id'][row]
            a.name         = self.search_result['config_name'][row]
            a.description  = self.search_result['config_description'][row]
            a.config_ctime = self.search_result['config_ctime'][row]

            self.textEdit_description.setText(a.description)

            a.ref_step_size = self.search_result['config_ref_step_size'][row]
            out = self.db.getColumnDataFromTable(
                'config_table',
                column_name_list=['group_name_id', 'channel_id',
                                  'config_weight', 'config_caput_enabled'],
                condition_str='config_id={0:d}'.format(
                    self.search_result['config_id'][row]))

            if out != []:
                (a.group_name_ids, a.channel_ids, a.weights,
                 a.caput_enabled_rows) = map(list, out)
            else:
                (a.group_name_ids, a.channel_ids, a.weights,
                 a.caput_enabled_rows) = [], [], [], []

            a.weights = [w if w is not None else np.nan for w in a.weights]

        self.config_model.table.updateModel()
        self.config_model.table.repaint()
Exemplo n.º 43
0
class LayerStackModel(QAbstractListModel):
    canMoveSelectedUp = pyqtSignal("bool")
    canMoveSelectedDown = pyqtSignal("bool")
    canDeleteSelected = pyqtSignal("bool")
    
    orderChanged = pyqtSignal()
    
    def __init__(self, parent = None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.onSelectionChanged)
        QTimer.singleShot(0, self.updateGUI)
        
    def __repr__(self):
        return "<LayerStackModel: layerStack='%r'>" % (self._layerStack,)  
    
    def __getitem__(self, i):
        return self._layerStack[-i-1]
    
    def __iter__(self):
        return reversed(self._layerStack)
        
    def updateGUI(self):
        self.canMoveSelectedUp.emit(self.selectedRow()>0)
        self.canMoveSelectedDown.emit(self.selectedRow()<self.rowCount()-1)
        self.canDeleteSelected.emit(self.rowCount() > 0)
        self.wantsUpdate()
    
    def append(self, data):
        #self.insertRow(self.rowCount())
        #self.setData(self.index(self.rowCount()-1), data)
        self.insertRow(0)
        self.setData(self.index(0), data)
    
    def selectedRow(self):
        selected = self.selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1
    
    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()
    
    def onSelectionChanged(self, selected, deselected):
        if len(deselected) > 0:
            self._layerStack[deselected[0].indexes()[0].row()].mode = 'ReadOnly'
        if len(selected) > 0:
            self._layerStack[selected[0].indexes()[0].row()].mode = 'Expanded'
        self.updateGUI()
    
    def rowCount(self, parent = QModelIndex()):
        if not parent.isValid():
            return len(self._layerStack)
        return 0
    
    def insertRows(self, row, count, parent = QModelIndex()):
        if parent.isValid():
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0,row)
        endRow   = min(row+count-1, len(self._layerStack))
        self.beginInsertRows(parent, beginRow, endRow) 
        while(beginRow <= endRow):
            self._layerStack.insert(row, Layer())
            beginRow += 1
        self.endInsertRows()
        assert self.rowCount() == oldRowCount+1
        return True
            
    def removeRows(self, row, count, parent = QModelIndex()):
        if parent.isValid():
            return False
        if row+count <= 0 or row >= len(self._layerStack):
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0,row)
        endRow   = min(row+count-1, len(self._layerStack)-1)
        self.beginRemoveRows(parent, beginRow, endRow)
        while(beginRow <= endRow):
            del self._layerStack[row]
            beginRow += 1
        
        self.endRemoveRows()
        assert self.rowCount() == oldRowCount-1
        return True
    
    def flags(self, index):
        defaultFlags = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
        if index.isValid():
            return Qt.ItemIsDragEnabled | defaultFlags
        else:
            return Qt.ItemIsDropEnabled | defaultFlags
    
    def supportedDropActions(self):
        return Qt.MoveAction
    
    def data(self, index, role):
        if not index.isValid():
            return None
        if index.row() > len(self._layerStack):
            return None
        
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._layerStack[index.row()]
        
        return None
    
    def setData(self, index, value, role = Qt.EditRole):
        layer = value
        if not isinstance(value, Layer):
            layer = value.toPyObject()
        self._layerStack[index.row()] = layer
        self.dataChanged.emit(index, index)
        return True
    
    def headerData(section, orientation, role = Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return QString("Column %1").arg(section)
        else:
            return QString("Row %1").arg(section)
        
    def wantsUpdate(self):
        self.layoutChanged.emit()

    def deleteSelected(self):
        print "delete"
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        self.removeRow(row.row())
        if self.rowCount() > 0:
            self.selectionModel.select(self.index(0), QItemSelectionModel.Select)
        self.updateGUI()

    def moveSelectedUp(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = oldRow - 1
            d = self._layerStack[oldRow]
            self.removeRow(oldRow)
            self.insertRow(newRow)
            self.setData(self.index(newRow), d)
            self.selectionModel.select(self.index(newRow), QItemSelectionModel.Select)
            self.orderChanged.emit()
            self.updateGUI()
    
    def moveSelectedDown(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = oldRow + 1
            d = self._layerStack[oldRow]
            self.removeRow(oldRow)
            self.insertRow(newRow)
            self.setData(self.index(newRow), d)
            self.selectionModel.select(self.index(newRow), QItemSelectionModel.Select)
            self.orderChanged.emit()
            self.updateGUI()
Exemplo n.º 44
0
class LayerStackModel(QAbstractListModel):
    canMoveSelectedUp = pyqtSignal("bool")
    canMoveSelectedDown = pyqtSignal("bool")
    canDeleteSelected = pyqtSignal("bool")
    
    orderChanged = pyqtSignal()
    layerAdded = pyqtSignal( Layer, int ) # is now in row
    layerRemoved = pyqtSignal( Layer, int ) # was in row
    stackCleared = pyqtSignal()
        
    def __init__(self, parent = None):
        QAbstractListModel.__init__(self, parent)
        self._layerStack = []
        self.selectionModel = QItemSelectionModel(self)
        self.selectionModel.selectionChanged.connect(self.updateGUI)
        self._movingRows = False
        QTimer.singleShot(0, self.updateGUI)

    ####
    ## High level API to manipulate the layerstack
    ###
    
    def __len__(self):
        return self.rowCount()
        
    def __repr__(self):
        return "<LayerStackModel: layerStack='%r'>" % (self._layerStack,)  
    
    def __getitem__(self, i):
        return self._layerStack[i]
    
    def __iter__(self):
        return self._layerStack.__iter__()
    
    def layerIndex(self, layer):
        #note that the 'index' function already has a different implementation
        #from Qt side
        return self._layerStack.index(layer)

    def append(self, data):
        self.insert(0, data)
   
    def clear(self):
        if len(self) > 0:
            self.removeRows(0,len(self))
            self.stackCleared.emit()

    def insert(self, index, data):
        self.insertRow(index)
        self.setData(self.index(index), data)
        if self.selectedRow() >= 0:
            self.selectionModel.select(self.index(self.selectedRow()), QItemSelectionModel.Deselect)
        self.selectionModel.select(self.index(index), QItemSelectionModel.Select)
        
        def onChanged():
            #assumes that data is unique!
            idx = self.index(self._layerStack.index(data))
            self.dataChanged.emit(idx, idx)
            self.updateGUI()
        data.changed.connect(onChanged)
        self.layerAdded.emit( data, self._layerStack.index(data))
        self.updateGUI()

    def selectRow( self, row ):
        self.selectionModel.setCurrentIndex( self.index(row), QItemSelectionModel.SelectCurrent)

    @pyqtSignature("deleteSelected()")
    def deleteSelected(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        layer = self._layerStack[row.row()]
        self.removeRow(row.row())
        if self.rowCount() > 0:
            self.selectionModel.select(self.index(0), QItemSelectionModel.Select)
        self.layerRemoved.emit( layer, row.row() )
        self.updateGUI()

    @pyqtSignature("moveSelectedUp()")
    def moveSelectedUp(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != 0:
            oldRow = row.row()
            newRow = oldRow - 1
            d = self._layerStack[oldRow]
            self.removeRow(oldRow)
            self.insertRow(newRow)
            self.setData(self.index(newRow), d)
            self.selectionModel.select(self.index(newRow), QItemSelectionModel.Select)
            self.orderChanged.emit()
            self.updateGUI()
    
    @pyqtSignature("moveSelectedDown()")
    def moveSelectedDown(self):
        assert len(self.selectionModel.selectedRows()) == 1
        row = self.selectionModel.selectedRows()[0]
        if row.row() != self.rowCount() - 1:
            oldRow = row.row()
            newRow = oldRow + 1
            d = self._layerStack[oldRow]
            self.removeRow(oldRow)
            self.insertRow(newRow)
            self.setData(self.index(newRow), d)
            self.selectionModel.select(self.index(newRow), QItemSelectionModel.Select)
            self.orderChanged.emit()
            self.updateGUI()
       
    ####
    ## Low level API. To add, remove etc. layers use the high level API from above.
    ####
 
    def updateGUI(self):
        self.canMoveSelectedUp.emit(self.selectedRow()>0)
        self.canMoveSelectedDown.emit(self.selectedRow()<self.rowCount()-1)
        self.canDeleteSelected.emit(self.rowCount() > 0)
        self.wantsUpdate()
        
    def selectedRow(self):
        selected = self.selectionModel.selectedRows()
        if len(selected) == 1:
            return selected[0].row()
        return -1
    
    def selectedIndex(self):
        row = self.selectedRow()
        if row >= 0:
            return self.index(self.selectedRow())
        else:
            return QModelIndex()
    
    def rowCount(self, parent = QModelIndex()):
        if not parent.isValid():
            return len(self._layerStack)
        return 0
    
    def insertRows(self, row, count, parent = QModelIndex()):
        '''Insert empty rows in the stack. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Always use the insert() or append() method.
        
        '''
        if parent.isValid():
            return False
        oldRowCount = self.rowCount()
        #for some reason, row can be negative!
        beginRow = max(0,row)
        endRow   = min(beginRow+count-1, len(self._layerStack))
        self.beginInsertRows(parent, beginRow, endRow) 
        while(beginRow <= endRow):
            self._layerStack.insert(row, Layer())
            beginRow += 1
        self.endInsertRows()
        assert self.rowCount() == oldRowCount+1, "oldRowCount = %d, self.rowCount() = %d" % (oldRowCount, self.rowCount())
        return True
            
    def removeRows(self, row, count, parent = QModelIndex()):
        '''Remove rows from the stack. 
        
        DO NOT USE THIS METHOD TO REMOVE LAYERS!
        Use the deleteSelected() method instead.
        
        '''

        if parent.isValid():
            return False
        if row+count <= 0 or row >= len(self._layerStack):
            return False
        oldRowCount = self.rowCount()
        beginRow = max(0,row)
        endRow   = min(row+count-1, len(self._layerStack)-1)
        self.beginRemoveRows(parent, beginRow, endRow)
        while(beginRow <= endRow):
            del self._layerStack[row]
            beginRow += 1
        self.endRemoveRows()
        return True
    
    def flags(self, index):
        defaultFlags = Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
        if index.isValid():
            return Qt.ItemIsDragEnabled | defaultFlags
        else:
            return Qt.ItemIsDropEnabled | defaultFlags
    
    def supportedDropActions(self):
        return Qt.MoveAction
    
    def data(self, index, role = Qt.DisplayRole):
        if not index.isValid():
            return None
        if index.row() > len(self._layerStack):
            return None
        
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self._layerStack[index.row()]
        
        return None
    
    def setData(self, index, value, role = Qt.EditRole):
        '''Replace one layer with another. 
        
        DO NOT USE THIS METHOD TO INSERT NEW LAYERS!
        Use deleteSelected() followed by insert() or append().
        
        '''
        layer = value
        if not isinstance(value, Layer):
            layer = value.toPyObject()
        self._layerStack[index.row()] = layer
        self.dataChanged.emit(index, index)
        return True
    
    def headerData(self, section, orientation, role = Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return None
        if orientation == Qt.Horizontal:
            return "Column %r" % section
        else:
            return "Row %r" % section
        
    def wantsUpdate(self):
        self.layoutChanged.emit()
Exemplo n.º 45
0
 def select(self, index, flags=QItemSelectionModel.ClearAndSelect):
     if isinstance(index, int):
         index = self.model().index(index)
     return QItemSelectionModel.select(self, index, flags)
Exemplo n.º 46
0
    def createWidgets(self):
        ## Message Table
        self.table = QTableView()
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setGridStyle(Qt.NoPen)

        self.model = QStandardItemModel(8, 3, self)
        self.model.setHeaderData(0, Qt.Horizontal, "From")
        self.model.setHeaderData(1, Qt.Horizontal, "Subject")
        self.model.setHeaderData(2, Qt.Horizontal, "Received")

        self.table.setModel(self.model)
        self.selectionModel = QItemSelectionModel(self.model)
        self.selectionModel.SelectionFlag = 0x0020
        self.table.setSelectionModel(self.selectionModel)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.verticalHeader().setVisible(False)
        self.table.setSortingEnabled(True)
        self.table.setAlternatingRowColors(True)

        ## Folder Tree View
        self.folderTree = QTreeWidget()
        self.folderTree.setColumnCount(1)
        self.folderTree.setHeaderLabel(QString('Folders'))

        self.treeItem = QTreeWidgetItem()
        self.treeItem.setText(0, 'Folders')

        self.inbox = QTreeWidgetItem()
        self.inbox.setText(0, 'Inbox')

        self.deletedItems = QTreeWidgetItem()
        self.deletedItems.setText(0, 'Deleted Items')

        self.drafts = QTreeWidgetItem()
        self.drafts.setText(0, 'Drafts')

        self.junk = QTreeWidgetItem()
        self.junk.setText(0, 'Junk')

        self.outbox = QTreeWidgetItem()
        self.outbox.setText(0, 'Outbox')

        self.sent = QTreeWidgetItem()
        self.sent.setText(0, 'Sent')

        self.treeItem.addChild(self.inbox)
        self.treeItem.addChild(self.deletedItems)
        self.treeItem.addChild(self.drafts)
        self.treeItem.addChild(self.junk)
        self.treeItem.addChild(self.outbox)
        self.treeItem.addChild(self.sent)

        self.folderTree.addTopLevelItem(self.treeItem)
        self.folderTree.expandAll()
        self.folderTree.setAnimated(True)

        self.folderTree.setMaximumWidth(150)

        ## Temp. placeholders
        self.textEdit = QTextEdit()
        self.textEdit2 = QTextEdit()