~ubuntu-core-dev/software-properties/main

« back to all changes in this revision

Viewing changes to softwareproperties/qt/DialogMirror.py

  • Committer: Simon Quigley
  • Date: 2018-07-14 10:11:32 UTC
  • mto: This revision was merged to the branch mainline in revision 1049.
  • Revision ID: tsimonq2@ubuntu.com-20180714101132-jpm43js9q13vplzm
Use sed to make everything say Qt.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#  Qt 4 based frontend to software-properties
 
2
#
 
3
#  Copyright (c) 2007 Canonical Ltd.
 
4
#
 
5
#  Author: Jonathan Riddell <jriddell@ubuntu.com>
 
6
#
 
7
#  This program is free software; you can redistribute it and/or
 
8
#  modify it under the terms of the GNU General Public License as
 
9
#  published by the Free Software Foundation; either version 2 of the
 
10
#  License, or (at your option) any later version.
 
11
#
 
12
#  This program is distributed in the hope that it will be useful,
 
13
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#  GNU General Public License for more details.
 
16
#
 
17
#  You should have received a copy of the GNU General Public License
 
18
#  along with this program; if not, write to the Free Software
 
19
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
20
#  USA
 
21
 
 
22
from __future__ import absolute_import, print_function
 
23
 
 
24
from gettext import gettext as _
 
25
import os
 
26
import threading
 
27
 
 
28
from softwareproperties.MirrorTest import MirrorTest
 
29
from .I18nHelper import *
 
30
 
 
31
from PyQt5.QtCore import *
 
32
from PyQt5.QtGui import *
 
33
from PyQt5 import uic
 
34
 
 
35
from softwareproperties.CountryInformation import CountryInformation
 
36
 
 
37
class DialogMirror(QDialog):
 
38
 
 
39
    # Signals
 
40
  test_start = pyqtSignal()
 
41
  test_end = pyqtSignal('QString')
 
42
  report_progress = pyqtSignal(int, int, tuple, tuple)
 
43
  report_action = pyqtSignal('QString')
 
44
 
 
45
  def __init__(self, parent, datadir, distro, custom_mirrors):
 
46
    """
 
47
    Initialize the dialog that allows to choose a custom or official mirror
 
48
    """
 
49
    QDialog.__init__(self, parent)
 
50
    uic.loadUi("%s/designer/dialog_mirror.ui" % datadir, self)
 
51
    self.parent = parent
 
52
 
 
53
    self.custom_mirrors = custom_mirrors
 
54
 
 
55
    self.country_info = CountryInformation()
 
56
 
 
57
    self.button_choose = self.buttonBox.button(QDialogButtonBox.Ok)
 
58
    self.button_choose.setEnabled(False)
 
59
    self.button_cancel = self.buttonBox.button(QDialogButtonBox.Cancel)
 
60
    self.distro = distro
 
61
 
 
62
    self.treeview.setColumnCount(1)
 
63
    self.treeview.setHeaderLabels([_("Mirror")])
 
64
 
 
65
    translate_widget(self)
 
66
    # used to find the corresponding iter of a location
 
67
    map_loc = {}
 
68
    patriot = None
 
69
    """ no custom yet
 
70
    # at first add all custom mirrors and a separator
 
71
    if len(self.custom_mirrors) > 0:
 
72
        for mirror in self.custom_mirrors:
 
73
 
 
74
            model.append(None, [mirror, False, True, None])
 
75
            self.column_mirror.add_attribute(self.renderer_mirror,
 
76
                                             "editable",
 
77
                                             COLUMN_CUSTOM)
 
78
        model.append(None, [None, True, False, None])
 
79
    """
 
80
    self.mirror_map = {}
 
81
    # secondly add all official mirrors
 
82
    for hostname in self.distro.source_template.mirror_set.keys():
 
83
        mirror = self.distro.source_template.mirror_set[hostname]
 
84
        if mirror.location in map_loc:  # a mirror in a country
 
85
            QTreeWidgetItem(map_loc[mirror.location], [hostname])
 
86
            self.mirror_map[hostname] = mirror
 
87
        elif mirror.location != None:  # a country new to the list
 
88
            country = self.country_info.get_country_name(mirror.location)
 
89
            parent = QTreeWidgetItem([country])
 
90
            self.mirror_map[country] = None
 
91
            self.treeview.addTopLevelItem(parent)
 
92
            QTreeWidgetItem(parent, [hostname])
 
93
            self.mirror_map[hostname] = mirror
 
94
            if mirror.location == self.country_info.code and patriot == None:
 
95
                patriot = parent
 
96
            map_loc[mirror.location] = parent
 
97
        else:  # a mirror without country
 
98
            item = QTreeWidgetItem([hostname])
 
99
            self.treeview.addTopLevelItem(item)
 
100
    self.treeview.sortItems(0, Qt.AscendingOrder)
 
101
    # Scroll to the local mirror set
 
102
    if patriot != None:
 
103
        self.select_mirror(patriot.text(0))
 
104
    self.treeview.itemClicked.connect(self.on_treeview_mirrors_cursor_changed)
 
105
    self.button_find_server.clicked.connect(self.on_button_test_clicked)
 
106
    self.edit_buttons_frame.hide()  ##FIXME not yet implemented
 
107
 
 
108
  def on_treeview_mirrors_cursor_changed(self, item, column):
 
109
    """ Check if the currently selected row in the mirror list
 
110
        contains a mirror and or is editable """
 
111
    # Update the list of available protocolls
 
112
    hostname = self.treeview.currentItem().text(0)
 
113
    mirror = self.mirror_map[hostname]
 
114
    self.combobox.clear()
 
115
    if mirror != None:
 
116
        self.combobox.setEnabled(True)
 
117
        seen_protos = []
 
118
        self.protocol_paths = {}
 
119
        for repo in mirror.repositories:
 
120
            # Only add a repository for a protocoll once
 
121
            if repo.proto in seen_protos:
 
122
                continue
 
123
            seen_protos.append(repo.proto)
 
124
            self.protocol_paths[repo.get_info()[0]] = repo.get_info()[1]
 
125
            self.combobox.addItem(repo.get_info()[0])
 
126
        self.button_choose.setEnabled(True)
 
127
    else:
 
128
        self.button_choose.setEnabled(False)
 
129
    """
 
130
        # Allow to edit and remove custom mirrors
 
131
        self.button_remove.set_sensitive(model.get_value(iter, COLUMN_CUSTOM))
 
132
        self.button_edit.set_sensitive(model.get_value(iter, COLUMN_CUSTOM))
 
133
        self.button_choose.set_sensitive(self.is_valid_mirror(model.get_value(iter, COLUMN_URI)))
 
134
        self.combobox.set_sensitive(False)
 
135
 
 
136
    """
 
137
 
 
138
  def run(self):
 
139
    """ Run the chooser dialog and return the chosen mirror or None """
 
140
    res = self.exec_()
 
141
 
 
142
    # FIXME: we should also return the list of custom servers
 
143
    if res == QDialog.Accepted:
 
144
        hostname = self.treeview.currentItem().text(0)
 
145
        mirror = self.mirror_map[hostname]
 
146
 
 
147
        if mirror == None:
 
148
            # Return the URL of the selected custom mirror
 
149
            print("Error, unknown mirror")
 
150
            return None
 
151
            ##FIXME return model.get_value(iter, COLUMN_URI)
 
152
        else:
 
153
            # Return a URL created from the hostname and the selected
 
154
            # repository
 
155
            proto = self.combobox.currentText()
 
156
 
 
157
            directory = self.protocol_paths[proto]
 
158
            return "%s://%s/%s" % (proto, mirror.hostname, directory)
 
159
    else:
 
160
        return None
 
161
 
 
162
  def on_button_test_clicked(self):
 
163
    ''' Perform a test to find the best mirror and select it
 
164
        afterwards in the treeview '''
 
165
    class MirrorTestQt(MirrorTest):
 
166
        def __init__(self, mirrors, test_file, running, dialog, parent):
 
167
            MirrorTest.__init__(self, mirrors, test_file, None, running)
 
168
            self.dialog = dialog
 
169
            self.parent = parent
 
170
 
 
171
        def report_action(self, text):
 
172
            if self.running.isSet():
 
173
                self.parent.report_action.emit(text)
 
174
 
 
175
        def report_progress(self, current, max, borders=(0,1), mod=(0,0)):
 
176
            if self.running.isSet():
 
177
                self.parent.report_progress.emit(current, max, borders, mod)
 
178
 
 
179
        def run(self):
 
180
            self.parent.test_start.emit()
 
181
            rocker = self.run_full_test()
 
182
            self.parent.test_end.emit(rocker)
 
183
 
 
184
    self.dialog = QProgressDialog(_("Testing Mirrors"), _("Cancel"), 0, 100, self)
 
185
    self.dialog.setWindowTitle(_("Testing Mirrors"))
 
186
    self.dialog.setWindowModality(Qt.WindowModal)
 
187
    self.button_cancel_test = QPushButton(_("Cancel"), self.dialog)
 
188
    self.dialog.setCancelButton(self.button_cancel_test)
 
189
    self.button_cancel_test.clicked.connect(self.on_button_cancel_test_clicked);
 
190
    # the following signals are connected across threads
 
191
    self.test_start.connect(self.on_test_start, Qt.BlockingQueuedConnection)
 
192
    self.test_end.connect(self.on_test_end, Qt.BlockingQueuedConnection)
 
193
    self.report_progress.connect(self.on_report_progress, Qt.BlockingQueuedConnection)
 
194
    self.report_action.connect(self.on_report_action, Qt.BlockingQueuedConnection)
 
195
 
 
196
    self.running = threading.Event()
 
197
    self.running.set()
 
198
    pipe = os.popen("dpkg --print-architecture")
 
199
    arch = pipe.read().strip()
 
200
    test_file = "dists/%s/%s/binary-%s/Packages.gz" % \
 
201
                 (self.distro.source_template.name,
 
202
                  self.distro.source_template.components[0].name,
 
203
                  arch)
 
204
    test = MirrorTestQt(list(self.distro.source_template.mirror_set.values()),
 
205
                         test_file, self.running, self.dialog, self)
 
206
    test.start() # test starts in a separate thread
 
207
 
 
208
  def on_test_start(self):
 
209
      self.dialog.show()
 
210
 
 
211
  def on_test_end(self, mirror):
 
212
      self.dialog.hide()
 
213
      if not self.running.isSet():
 
214
          return # canceled by user
 
215
      if mirror != None:
 
216
          self.select_mirror(mirror)
 
217
      else:
 
218
          QMessageBox.warning(self.dialog, _("Testing Mirrors"),
 
219
                                  _("No suitable download server was found") + "\n" +
 
220
                                  _("Please check your Internet connection."))
 
221
 
 
222
  def on_report_action(self, text):
 
223
      self.dialog.setLabelText(str("<i>%s</i>" % text))
 
224
 
 
225
  def on_report_progress(self, current, max, borders=(0,1), mod=(0,0)):
 
226
      #self.dialog.setLabelText(_("Completed %s of %s tests") % \
 
227
      #                       (current + mod[0], max + mod[1]))
 
228
      frac = borders[0] + (borders[1] - borders[0]) / max * current
 
229
      self.dialog.setValue(frac*100)
 
230
 
 
231
  def on_button_cancel_test_clicked(self):
 
232
    ''' Abort the mirror performance test '''
 
233
    self.running.clear()
 
234
    self.dialog.show()
 
235
    self.dialog.setLabelText("<i>%s</i>" % _("Canceling..."))
 
236
    self.button_cancel_test.setEnabled(False)
 
237
    self.dialog.setValue(100)
 
238
 
 
239
  def select_mirror(self, mirror):
 
240
    """Select and expand the path to a matching mirror in the list"""
 
241
    found = self.treeview.findItems(mirror, Qt.MatchExactly|Qt.MatchRecursive)
 
242
    if found:
 
243
      found[0].setSelected(True)
 
244
      self.treeview.setCurrentItem(found[0])
 
245
      self.treeview.scrollToItem(found[0], QAbstractItemView.PositionAtCenter)
 
246
      self.on_treeview_mirrors_cursor_changed(found[0], 0)
 
247
      self.button_choose.setFocus()
 
248
      return True