Exemple #1
0
class AddWindow(SubProcessDialog):
    def __init__(self,
                 tree,
                 selected_list,
                 dialog=True,
                 ui_mode=True,
                 parent=None,
                 local=None,
                 message=None):
        self.tree = tree
        self.initial_selected_list = selected_list

        super(AddWindow, self).__init__(
            gettext("Add"),
            name="add",
            default_size=(400, 400),
            ui_mode=ui_mode,
            dialog=dialog,
            parent=parent,
            hide_progress=True,
        )

        self.throbber = ThrobberWidget(self)

        # Display the list of unversioned files
        groupbox = QtGui.QGroupBox(gettext("Unversioned Files"), self)
        vbox = QtGui.QVBoxLayout(groupbox)

        self.filelist = TreeWidget(groupbox)
        self.filelist.throbber = self.throbber
        self.filelist.tree_model.is_item_in_select_all = lambda item: (
            # Is in select all. - Not versioned, and not Ignored
            item.change is not None and item.change.is_ignored(
            ) is None and not item.change.is_versioned(),

            # look at children. - Not ignored
            item.change is not None and item.change.is_ignored() is None or
            item.change is None)

        def filter_context_menu():
            items = self.filelist.get_selection_items()
            selection_len = len(items)
            single_file = (selection_len == 1 and items[0].item.kind == "file")
            single_item_in_tree = (selection_len == 1
                                   and (items[0].change is None
                                        or items[0].change[6][1] is not None))

            self.filelist.action_open_file.setEnabled(True)
            self.filelist.action_open_file.setVisible(True)
            self.filelist.action_show_file.setEnabled(single_file)
            self.filelist.action_show_file.setVisible(True)
            self.filelist.action_show_annotate.setVisible(False)
            self.filelist.action_show_log.setVisible(False)
            self.filelist.action_show_diff.setVisible(False)
            self.filelist.action_add.setVisible(False)
            self.filelist.action_revert.setVisible(False)
            self.filelist.action_merge.setVisible(False)
            self.filelist.action_resolve.setVisible(False)
            self.filelist.action_rename.setVisible(True)
            self.filelist.action_rename.setEnabled(single_item_in_tree)
            self.filelist.action_remove.setVisible(False)
            self.filelist.action_mark_move.setVisible(False)

        self.filelist.filter_context_menu = filter_context_menu

        vbox.addWidget(self.filelist)

        selectall_checkbox = SelectAllCheckBox(self.filelist, groupbox)
        vbox.addWidget(selectall_checkbox)
        selectall_checkbox.setCheckState(QtCore.Qt.Checked)
        selectall_checkbox.setEnabled(True)

        self.show_ignored_checkbox = QtGui.QCheckBox(
            gettext("Show ignored files"), groupbox)
        vbox.addWidget(self.show_ignored_checkbox)
        self.connect(self.show_ignored_checkbox,
                     QtCore.SIGNAL("toggled(bool)"), self.show_ignored)

        # groupbox gets disabled as we are executing.
        QtCore.QObject.connect(self, QtCore.SIGNAL("disableUi(bool)"),
                               groupbox, QtCore.SLOT("setDisabled(bool)"))

        self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
        self.splitter.addWidget(groupbox)
        self.splitter.addWidget(self.make_default_status_box())
        self.splitter.setStretchFactor(0, 10)
        self.restoreSplitterSizes([150, 150])

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.throbber)
        layout.addWidget(self.splitter)
        layout.addWidget(self.buttonbox)
        self.throbber.show()

    def show(self):
        SubProcessDialog.show(self)
        QtCore.QTimer.singleShot(1, self.initial_load)

    @runs_in_loading_queue
    @ui_current_widget
    @reports_exception()
    def initial_load(self):
        self.filelist.tree_model.checkable = True
        fmodel = self.filelist.tree_filter_model
        fmodel.setFilter(fmodel.CHANGED, False)
        fmodel.setFilter(fmodel.UNCHANGED, False)
        self.filelist.set_tree(
            self.tree,
            changes_mode=True,
            initial_checked_paths=self.initial_selected_list,
            change_load_filter=lambda c: not c.is_versioned())
        self.throbber.hide()

    def _get_files_to_add(self):
        return [ref.path for ref in self.filelist.tree_model.iter_checked()]

    def validate(self):
        if not self._get_files_to_add():
            self.operation_blocked(gettext("Nothing selected to add"))
            return False
        return True

    def do_start(self):
        """Add the files."""
        files = self._get_files_to_add()
        self.process_widget.do_start(self.tree.basedir, "add", "--no-recurse",
                                     *files)

    def show_ignored(self, state):
        """Show/hide ignored files."""
        fmodel = self.filelist.tree_filter_model
        fmodel.setFilter(fmodel.IGNORED, state)
        #self.filelist.update_selectall_state(None, None)

    def _saveSize(self, config):
        SubProcessDialog._saveSize(self, config)
        self._saveSplitterSizes(config, self.splitter)
Exemple #2
0
    def __init__(self,
                 tree,
                 selected_list,
                 dialog=True,
                 ui_mode=True,
                 parent=None,
                 local=None,
                 message=None):
        self.tree = tree
        self.initial_selected_list = selected_list

        super(AddWindow, self).__init__(
            gettext("Add"),
            name="add",
            default_size=(400, 400),
            ui_mode=ui_mode,
            dialog=dialog,
            parent=parent,
            hide_progress=True,
        )

        self.throbber = ThrobberWidget(self)

        # Display the list of unversioned files
        groupbox = QtGui.QGroupBox(gettext("Unversioned Files"), self)
        vbox = QtGui.QVBoxLayout(groupbox)

        self.filelist = TreeWidget(groupbox)
        self.filelist.throbber = self.throbber
        self.filelist.tree_model.is_item_in_select_all = lambda item: (
            # Is in select all. - Not versioned, and not Ignored
            item.change is not None and item.change.is_ignored(
            ) is None and not item.change.is_versioned(),

            # look at children. - Not ignored
            item.change is not None and item.change.is_ignored() is None or
            item.change is None)

        def filter_context_menu():
            items = self.filelist.get_selection_items()
            selection_len = len(items)
            single_file = (selection_len == 1 and items[0].item.kind == "file")
            single_item_in_tree = (selection_len == 1
                                   and (items[0].change is None
                                        or items[0].change[6][1] is not None))

            self.filelist.action_open_file.setEnabled(True)
            self.filelist.action_open_file.setVisible(True)
            self.filelist.action_show_file.setEnabled(single_file)
            self.filelist.action_show_file.setVisible(True)
            self.filelist.action_show_annotate.setVisible(False)
            self.filelist.action_show_log.setVisible(False)
            self.filelist.action_show_diff.setVisible(False)
            self.filelist.action_add.setVisible(False)
            self.filelist.action_revert.setVisible(False)
            self.filelist.action_merge.setVisible(False)
            self.filelist.action_resolve.setVisible(False)
            self.filelist.action_rename.setVisible(True)
            self.filelist.action_rename.setEnabled(single_item_in_tree)
            self.filelist.action_remove.setVisible(False)
            self.filelist.action_mark_move.setVisible(False)

        self.filelist.filter_context_menu = filter_context_menu

        vbox.addWidget(self.filelist)

        selectall_checkbox = SelectAllCheckBox(self.filelist, groupbox)
        vbox.addWidget(selectall_checkbox)
        selectall_checkbox.setCheckState(QtCore.Qt.Checked)
        selectall_checkbox.setEnabled(True)

        self.show_ignored_checkbox = QtGui.QCheckBox(
            gettext("Show ignored files"), groupbox)
        vbox.addWidget(self.show_ignored_checkbox)
        self.connect(self.show_ignored_checkbox,
                     QtCore.SIGNAL("toggled(bool)"), self.show_ignored)

        # groupbox gets disabled as we are executing.
        QtCore.QObject.connect(self, QtCore.SIGNAL("disableUi(bool)"),
                               groupbox, QtCore.SLOT("setDisabled(bool)"))

        self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
        self.splitter.addWidget(groupbox)
        self.splitter.addWidget(self.make_default_status_box())
        self.splitter.setStretchFactor(0, 10)
        self.restoreSplitterSizes([150, 150])

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.throbber)
        layout.addWidget(self.splitter)
        layout.addWidget(self.buttonbox)
        self.throbber.show()
Exemple #3
0
 def assertSelectedPaths(self, treewidget, paths):
     if 0: treewidget = TreeWidget()
     selected = [item.path for item in treewidget.tree_model.iter_checked()]
     # we do not care for the order in this test.
     self.assertEqual(set(selected), set(paths))
Exemple #4
0
    def test_show_widget(self):
        widget = TreeWidget()
        self.widget = widget
        self.run_model_tests()

        self.addCleanup(widget.close)
        # make the widget bigger so that we can see what is going on.
        widget.setGeometry(0, 0, 500, 500)
        widget.show()
        QtCore.QCoreApplication.processEvents()
        widget.set_tree(self.tree, self.branch, changes_mode=self.changes_mode)
        self.run_model_tests()

        widget.update()
        QtCore.QCoreApplication.processEvents()
        widget.expandAll()
        self.run_model_tests()

        widget.update()
        QtCore.QCoreApplication.processEvents()

        self.modify_tree(self, self.tree)
        widget.refresh()
        self.run_model_tests()

        widget.update()
        QtCore.QCoreApplication.processEvents()
        widget.expandAll()
        self.run_model_tests()

        widget.update()
        QtCore.QCoreApplication.processEvents()
Exemple #5
0
 def filter_context_menu():
     TreeWidget.filter_context_menu(self.filelist)
     self.filelist.action_add.setVisible(False)
     self.filelist.action_revert.setVisible(False)
Exemple #6
0
    def __init__(self,
                 tree,
                 selected_list,
                 dialog=True,
                 parent=None,
                 local=None,
                 message=None,
                 ui_mode=True,
                 backup=True):
        self.tree = tree
        self.has_pending_merges = len(tree.get_parent_ids()) > 1
        self.initial_selected_list = selected_list

        SubProcessDialog.__init__(self,
                                  gettext("Revert"),
                                  name="revert",
                                  default_size=(400, 400),
                                  ui_mode=ui_mode,
                                  dialog=dialog,
                                  parent=parent,
                                  hide_progress=True)

        self.throbber = ThrobberWidget(self)

        # Display the list of changed files
        self.file_groupbox = QtGui.QGroupBox(
            gettext("Select changes to revert"), self)

        self.filelist = TreeWidget(self.file_groupbox)
        self.filelist.throbber = self.throbber
        self.filelist.tree_model.set_select_all_kind('versioned')

        def filter_context_menu():
            TreeWidget.filter_context_menu(self.filelist)
            self.filelist.action_add.setVisible(False)
            self.filelist.action_revert.setVisible(False)

        self.filelist.filter_context_menu = filter_context_menu

        self.selectall_checkbox = SelectAllCheckBox(self.filelist,
                                                    self.file_groupbox)
        self.selectall_checkbox.setEnabled(True)

        self.no_backup_checkbox = QtGui.QCheckBox(
            gettext('Do not save backups of reverted files'))
        if not backup:
            self.no_backup_checkbox.setCheckState(QtCore.Qt.Checked)
        self.no_backup_checkbox.setEnabled(True)

        filesbox = QtGui.QVBoxLayout(self.file_groupbox)
        filesbox.addWidget(self.filelist)
        filesbox.addWidget(self.selectall_checkbox)
        filesbox.addWidget(self.no_backup_checkbox)

        if self.has_pending_merges:
            self.file_groupbox.setCheckable(True)
            self.merges_groupbox = QtGui.QGroupBox(
                gettext("Forget pending merges"))
            self.merges_groupbox.setCheckable(True)
            # This keeps track of what the merges_groupbox was before the
            # select all changes it, so that it can put it back to the state
            # it was.
            self.merges_base_checked = True
            self.pending_merges = PendingMergesList(self.processEvents,
                                                    self.throbber, self)
            merges_box = QtGui.QVBoxLayout(self.merges_groupbox)
            merges_box.addWidget(self.pending_merges)

            self.connect(self.selectall_checkbox,
                         QtCore.SIGNAL("stateChanged(int)"),
                         self.selectall_state_changed)
            self.connect(self.merges_groupbox, QtCore.SIGNAL("clicked(bool)"),
                         self.merges_clicked)
            self.connect(self.file_groupbox, QtCore.SIGNAL("clicked(bool)"),
                         self.file_groupbox_clicked)
            self.connect(
                self.filelist.tree_model,
                QtCore.SIGNAL("dataChanged(QModelIndex, QModelIndex)"),
                self.filelist_data_changed)

        # groupbox gets disabled as we are executing.
        QtCore.QObject.connect(self, QtCore.SIGNAL("disableUi(bool)"),
                               self.file_groupbox,
                               QtCore.SLOT("setDisabled(bool)"))

        self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
        self.splitter.addWidget(self.file_groupbox)
        if self.has_pending_merges:
            self.splitter.addWidget(self.merges_groupbox)

        self.splitter.addWidget(self.make_default_status_box())
        self.splitter.setStretchFactor(0, 10)
        self.restoreSplitterSizes([150, 150])

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.throbber)
        layout.addWidget(self.splitter)

        # Diff button to view changes in files selected to revert
        self.diffbuttons = DiffButtons(self)
        self.diffbuttons.setToolTip(
            gettext("View changes in files selected to revert"))
        self.connect(self.diffbuttons, QtCore.SIGNAL("triggered(QString)"),
                     self.show_diff_for_checked)
        hbox = QtGui.QHBoxLayout()
        hbox.addWidget(self.diffbuttons)
        hbox.addWidget(self.buttonbox)
        layout.addLayout(hbox)
        self.throbber.show()
Exemple #7
0
class RevertWindow(SubProcessDialog):
    def __init__(self,
                 tree,
                 selected_list,
                 dialog=True,
                 parent=None,
                 local=None,
                 message=None,
                 ui_mode=True,
                 backup=True):
        self.tree = tree
        self.has_pending_merges = len(tree.get_parent_ids()) > 1
        self.initial_selected_list = selected_list

        SubProcessDialog.__init__(self,
                                  gettext("Revert"),
                                  name="revert",
                                  default_size=(400, 400),
                                  ui_mode=ui_mode,
                                  dialog=dialog,
                                  parent=parent,
                                  hide_progress=True)

        self.throbber = ThrobberWidget(self)

        # Display the list of changed files
        self.file_groupbox = QtGui.QGroupBox(
            gettext("Select changes to revert"), self)

        self.filelist = TreeWidget(self.file_groupbox)
        self.filelist.throbber = self.throbber
        self.filelist.tree_model.set_select_all_kind('versioned')

        def filter_context_menu():
            TreeWidget.filter_context_menu(self.filelist)
            self.filelist.action_add.setVisible(False)
            self.filelist.action_revert.setVisible(False)

        self.filelist.filter_context_menu = filter_context_menu

        self.selectall_checkbox = SelectAllCheckBox(self.filelist,
                                                    self.file_groupbox)
        self.selectall_checkbox.setEnabled(True)

        self.no_backup_checkbox = QtGui.QCheckBox(
            gettext('Do not save backups of reverted files'))
        if not backup:
            self.no_backup_checkbox.setCheckState(QtCore.Qt.Checked)
        self.no_backup_checkbox.setEnabled(True)

        filesbox = QtGui.QVBoxLayout(self.file_groupbox)
        filesbox.addWidget(self.filelist)
        filesbox.addWidget(self.selectall_checkbox)
        filesbox.addWidget(self.no_backup_checkbox)

        if self.has_pending_merges:
            self.file_groupbox.setCheckable(True)
            self.merges_groupbox = QtGui.QGroupBox(
                gettext("Forget pending merges"))
            self.merges_groupbox.setCheckable(True)
            # This keeps track of what the merges_groupbox was before the
            # select all changes it, so that it can put it back to the state
            # it was.
            self.merges_base_checked = True
            self.pending_merges = PendingMergesList(self.processEvents,
                                                    self.throbber, self)
            merges_box = QtGui.QVBoxLayout(self.merges_groupbox)
            merges_box.addWidget(self.pending_merges)

            self.connect(self.selectall_checkbox,
                         QtCore.SIGNAL("stateChanged(int)"),
                         self.selectall_state_changed)
            self.connect(self.merges_groupbox, QtCore.SIGNAL("clicked(bool)"),
                         self.merges_clicked)
            self.connect(self.file_groupbox, QtCore.SIGNAL("clicked(bool)"),
                         self.file_groupbox_clicked)
            self.connect(
                self.filelist.tree_model,
                QtCore.SIGNAL("dataChanged(QModelIndex, QModelIndex)"),
                self.filelist_data_changed)

        # groupbox gets disabled as we are executing.
        QtCore.QObject.connect(self, QtCore.SIGNAL("disableUi(bool)"),
                               self.file_groupbox,
                               QtCore.SLOT("setDisabled(bool)"))

        self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
        self.splitter.addWidget(self.file_groupbox)
        if self.has_pending_merges:
            self.splitter.addWidget(self.merges_groupbox)

        self.splitter.addWidget(self.make_default_status_box())
        self.splitter.setStretchFactor(0, 10)
        self.restoreSplitterSizes([150, 150])

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.throbber)
        layout.addWidget(self.splitter)

        # Diff button to view changes in files selected to revert
        self.diffbuttons = DiffButtons(self)
        self.diffbuttons.setToolTip(
            gettext("View changes in files selected to revert"))
        self.connect(self.diffbuttons, QtCore.SIGNAL("triggered(QString)"),
                     self.show_diff_for_checked)
        hbox = QtGui.QHBoxLayout()
        hbox.addWidget(self.diffbuttons)
        hbox.addWidget(self.buttonbox)
        layout.addLayout(hbox)
        self.throbber.show()

    def show(self):
        SubProcessDialog.show(self)
        QtCore.QTimer.singleShot(1, self.initial_load)

    @runs_in_loading_queue
    @ui_current_widget
    @reports_exception()
    def initial_load(self):
        self.filelist.tree_model.checkable = True
        #fmodel.setFilter(fmodel.UNVERSIONED, False)
        if self.initial_selected_list is None and not self.has_pending_merges:
            self.initial_selected_list = []

        self.filelist.set_tree(
            self.tree,
            changes_mode=True,
            want_unversioned=False,
            initial_checked_paths=self.initial_selected_list)
        self.filelist_checked_base = list(
            self.filelist.tree_model.iter_checked())
        self.selectall_checkbox.update_state()
        self.processEvents()

        if self.has_pending_merges:
            self.pending_merges.load_tree(self.tree)
            self.processEvents()

        self.throbber.hide()

    # The logic for the next 4 methods is like this:
    # * Either file_groupbox or merges_groupbox or both must be checked,
    #   never neither.
    # * If merges_groupbox is checked, all files must be checked. If a file is
    #   unchecked, merges_groupbox must be unchecked.
    # Unless:
    # * file_groupbox is unchecked - then all files are unchecked.
    #
    # We keep a recored of what was checked, so that we we change something,
    # and then later we go back to a state where that change was not necessary,
    # we can return to what it was. This is stored in merges_base_checked, and
    # filelist_checked_base.

    def selectall_state_changed(self, state):
        if state == QtCore.Qt.Checked:
            self.merges_groupbox.setChecked(self.merges_base_checked)
        elif self.file_groupbox.isChecked():
            self.merges_groupbox.setChecked(False)

    def merges_clicked(self, state):
        self.merges_base_checked = state

        if state:
            if self.file_groupbox.isChecked():
                self.selectall_checkbox.clicked(QtCore.Qt.Checked)
            else:
                self.selectall_checkbox.clicked(QtCore.Qt.Unchecked)

        if not state:
            self.file_groupbox.setChecked(True)
            self.filelist.tree_model.set_checked_items(
                self.filelist_checked_base, ignore_no_file_error=True)

    def file_groupbox_clicked(self, state):
        if not state:
            self.merges_groupbox.setChecked(True)
            self.selectall_checkbox.clicked(QtCore.Qt.Unchecked)
        if state:
            if not self.merges_base_checked:
                self.filelist.tree_model.set_checked_items(
                    self.filelist_checked_base, ignore_no_file_error=True)
            else:
                self.selectall_checkbox.clicked(QtCore.Qt.Checked)

    def filelist_data_changed(self, start, end):
        if (self.file_groupbox.isChecked()
                and not self.merges_groupbox.isChecked()):
            self.filelist_checked_base = list(
                self.filelist.tree_model.iter_checked())

    def _is_revert_pending_merges(self):
        """Return True if selected to revert pending merges,
        False if not selected, None if there is no pending merges.
        """
        if not self.has_pending_merges:
            return None
        return bool(self.merges_groupbox.isChecked())

    def _get_files_to_revert(self):
        return [
            ref.path for ref in self.filelist.tree_model.iter_checked(
                include_unchanged_dirs=False)
        ]

    def validate(self):
        if (self._is_revert_pending_merges() is False
                and self.selectall_checkbox.checkState() == QtCore.Qt.Checked):

            if not self.ask_confirmation(
                    gettext("You have selected revert for all changed paths\n"
                            "but keep pending merges.\n\n"
                            "Do you want to continue?")):
                return False

        # It doesn't matter if selectall_checkbox checkbox is activated or not -
        # we really need to check if there are files selected, because you can
        # check the 'select all' checkbox if there are no files selectable.
        if not self._is_revert_pending_merges(
        ) and not self._get_files_to_revert():
            self.operation_blocked(
                gettext("You have not selected anything to revert."))
            return False

        return True

    def do_start(self):
        """Revert the files."""
        args = ["revert"]
        if (self._is_revert_pending_merges() is None
                or (self._is_revert_pending_merges() is False
                    and self.file_groupbox.isChecked())):
            args.extend(self._get_files_to_revert())
        if (self._is_revert_pending_merges() is True
                and not self.file_groupbox.isChecked()):
            args.append("--forget-merges")
        if self.no_backup_checkbox.checkState():
            args.append("--no-backup")
        self.process_widget.do_start(self.tree.basedir, *args)

    def _saveSize(self, config):
        SubProcessDialog._saveSize(self, config)
        self._saveSplitterSizes(config, self.splitter)

    def show_diff_for_checked(self, ext_diff=None, dialog_action='revert'):
        """Diff button clicked: show the diff for checked entries.

        @param  ext_diff:       selected external diff tool (if any)
        @param  dialog_action:  purpose of parent window (main action)
        """
        # XXX make this function universal for both qcommit and qrevert (?)
        checked = [ref.path for ref in self.filelist.tree_model.iter_checked()]

        if checked:
            arg_provider = InternalWTDiffArgProvider(
                self.tree.basis_tree().get_revision_id(),
                self.tree,
                self.tree.branch,
                self.tree.branch,
                specific_files=checked)

            show_diff(arg_provider,
                      ext_diff=ext_diff,
                      parent_window=self,
                      context=self.filelist.diff_context)

        else:
            msg = "No changes selected to " + dialog_action
            QtGui.QMessageBox.warning(self, "QBzr - " + gettext("Diff"),
                                      gettext(msg), QtGui.QMessageBox.Ok)