~usb-creator-hackers/usb-creator/trunk

« back to all changes in this revision

Viewing changes to usbcreator/frontends/kde/frontend.py

  • Committer: Harald Sitter
  • Date: 2015-02-16 09:34:19 UTC
  • mfrom: (442.1.11 usb-creator)
  • Revision ID: apachelogger@ubuntu.com-20150216093419-6vov2fdoqcvbk1p9
merge qt5 port

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
# Copyright (C) 2009 Roderick B. Greening <roderick.greening@gmail.com>
4
4
# Copyright (C) 2014 Harald Sitter <apachelogger@kubuntu.org>
5
 
 
5
#
6
6
# Based in part on work by:
7
7
#  David Edmundson <kde@davidedmundson.co.uk>
8
8
#  Canonical Ltd. USB Creator Team
9
 
 
9
#
10
10
# This program is free software: you can redistribute it and/or modify
11
11
# it under the terms of the GNU General Public License version 3,
12
12
# as published by the Free Software Foundation.
19
19
# You should have received a copy of the GNU General Public License
20
20
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
21
 
 
22
# TODO: When pykf5 becomes available qmessagebox should be ported back to kmessagebox
 
23
 
22
24
import sys
23
25
import os
24
26
 
25
 
from PyQt4.QtCore import *
26
 
from PyQt4.QtGui import *
27
 
from PyQt4 import uic
28
 
from PyKDE4.kdeui import KIcon, KMessageBox, KGlobalSettings
29
 
from PyKDE4.kdecore import KProcess, KStandardDirs, KUrl, i18n
30
 
from PyKDE4.kio import KFileDialog
 
27
from PyQt5 import uic
 
28
from PyQt5.QtCore import *
 
29
from PyQt5.QtGui import *
 
30
from PyQt5.QtWidgets import *
31
31
 
32
32
from usbcreator.frontends.kde.translate import translate
33
33
uic.properties.Properties._string = translate
51
51
class KdeFrontend(Frontend, QObject):
52
52
    @classmethod
53
53
    def startup_failure(cls, message):
54
 
        KMessageBox.sorry(None, message, "", KMessageBox.Notify)
 
54
        #KMessageBox.error(None, message)
 
55
        QMessageBox.critical(None, '', message)
 
56
        sys.exit(1)
55
57
 
56
58
    @classmethod
57
59
    def DBusMainLoop(cls):
92
94
        if self.__img is not None:
93
95
            self.__backend.add_image(misc.text_type(self.__img))
94
96
 
95
 
        downloadsDir = QDir(KGlobalSettings.self().downloadPath())
 
97
        downloadsDir = QDir(QStandardPaths.standardLocations(QStandardPaths.DownloadLocation)[0])
96
98
        isoFilter = []
97
99
        isoFilter.append("*.iso")
98
100
        for iso in downloadsDir.entryList(isoFilter, QDir.Files):
133
135
        if 'USBCREATOR_LOCAL' in os.environ:
134
136
            appdir = os.path.join(os.getcwd(), 'gui')
135
137
        else:
136
 
            file = KStandardDirs.locate("appdata", self.__mainWindow_ui)
 
138
            file = QStandardPaths.locate(QStandardPaths.DataLocation, self.__mainWindow_ui)
137
139
            appdir = file[:file.rfind("/")]
138
140
        uic.loadUi(misc.text_type(appdir + "/" + self.__mainWindow_ui), self.__mainWindow)
139
141
 
151
153
            self.__mainWindow.ui_persist_frame.hide()
152
154
 
153
155
        #hide sources if an argument was provided
154
 
        if self.__img is not None:
 
156
        if self.__img is not '':
155
157
            self.__mainWindow.ui_source_list.hide()
156
158
            self.__mainWindow.ui_add_source.hide()
157
159
            self.__mainWindow.source_label.hide()
161
163
        self.__mainWindow.ui_start_button.setEnabled(False)
162
164
 
163
165
        #add some buttons
164
 
        self.__mainWindow.ui_quit_button.setIcon(KIcon("application-exit"))
165
 
        self.__mainWindow.ui_start_button.setIcon(KIcon("dialog-ok-apply"))
166
 
        self.__mainWindow.ui_add_source.setIcon(KIcon("media-optical"))
167
 
        self.__mainWindow.ui_format_dest.setIcon(KIcon("drive-removable-media-usb-pendrive"))
 
166
        self.__mainWindow.ui_quit_button.setIcon(QIcon.fromTheme("application-exit"))
 
167
        self.__mainWindow.ui_start_button.setIcon(QIcon.fromTheme("dialog-ok-apply"))
 
168
        self.__mainWindow.ui_add_source.setIcon(QIcon.fromTheme("media-optical"))
 
169
        self.__mainWindow.ui_format_dest.setIcon(QIcon.fromTheme("drive-removable-media-usb-pendrive"))
168
170
 
169
171
        #set up signals
170
 
        self.connect(self.__mainWindow.ui_add_source,SIGNAL('clicked()'),
171
 
            self.add_file_source_dialog)
172
 
        self.connect(self.__mainWindow.ui_persist_slider,SIGNAL('valueChanged(int)'),
 
172
        self.__mainWindow.ui_add_source.clicked.connect(self.add_file_source_dialog)
 
173
        self.__mainWindow.ui_persist_slider.valueChanged.connect(
173
174
            lambda value: self.__mainWindow.ui_persist_label.setText(misc.format_mb_size(value)))
174
 
        self.connect(self.__mainWindow.ui_quit_button,SIGNAL('clicked()'),
175
 
            self.quit)
176
 
        self.connect(self.__mainWindow.ui_start_button,SIGNAL('clicked()'),
177
 
            self.install)
178
 
        self.connect(self.__mainWindow.ui_dest_list,SIGNAL(
179
 
            'currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)'),
180
 
            self.dest_selection_changed)
181
 
        self.connect(self.__mainWindow.ui_source_list,SIGNAL(
182
 
            'currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)'),
183
 
            self.source_selection_changed)
184
 
        self.connect(self.__mainWindow.ui_format_dest,SIGNAL('clicked()'),
185
 
            self.format_dest_clicked)
 
175
        self.__mainWindow.ui_quit_button.clicked.connect(self.quit)
 
176
        self.__mainWindow.ui_start_button.clicked.connect(self.install)
 
177
        self.__mainWindow.ui_dest_list.currentItemChanged.connect(self.dest_selection_changed)
 
178
        self.__mainWindow.ui_source_list.currentItemChanged.connect(self.source_selection_changed)
 
179
        self.__mainWindow.ui_format_dest.clicked.connect(self.format_dest_clicked)
 
180
 
 
181
        # FIXME: we need a custom delegate and elide the iso column on the left rather than the right
 
182
        #        otherwise long paths will take up the entire space while in fact the image name is the useful bit of information 90% of the time
186
183
 
187
184
        self.__mainWindow.ui_source_list.setSortingEnabled(True)
188
185
        self.__mainWindow.ui_source_list.sortByColumn(0, Qt.AscendingOrder)
194
191
        # usage.
195
192
        # Neither colum is resizable by the user, so additional tooltips are
196
193
        # enabled for the widgetitems (see add_source).
197
 
        self.__mainWindow.ui_source_list.header().setResizeMode(0, QHeaderView.Stretch)
198
 
        self.__mainWindow.ui_source_list.header().setResizeMode(1, QHeaderView.Stretch)
199
 
        self.__mainWindow.ui_source_list.header().setResizeMode(2, QHeaderView.ResizeToContents)
 
194
        self.__mainWindow.ui_source_list.header().setSectionResizeMode(0, QHeaderView.Stretch)
 
195
        self.__mainWindow.ui_source_list.header().setSectionResizeMode(1, QHeaderView.Stretch)
 
196
        self.__mainWindow.ui_source_list.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
200
197
        self.__mainWindow.ui_dest_list.setSortingEnabled(True)
201
198
        self.__mainWindow.ui_dest_list.sortByColumn(0, Qt.AscendingOrder)
202
199
        # For destinations only stretch the device column.
203
 
        self.__mainWindow.ui_dest_list.header().setResizeMode(0, QHeaderView.Stretch)
204
 
        self.__mainWindow.ui_dest_list.header().setResizeMode(1, QHeaderView.ResizeToContents)
205
 
        self.__mainWindow.ui_dest_list.header().setResizeMode(2, QHeaderView.ResizeToContents)
206
 
        self.__mainWindow.ui_dest_list.header().setResizeMode(3, QHeaderView.ResizeToContents)
207
 
        self.progress_bar = QProgressDialog("",i18n('Cancel'),0,100,self.__mainWindow)
 
200
        self.__mainWindow.ui_dest_list.header().setSectionResizeMode(0, QHeaderView.Stretch)
 
201
        self.__mainWindow.ui_dest_list.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
 
202
        self.__mainWindow.ui_dest_list.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
 
203
        self.__mainWindow.ui_dest_list.header().setSectionResizeMode(3, QHeaderView.ResizeToContents)
 
204
        self.progress_bar = QProgressDialog("",_('Cancel'),0,100,self.__mainWindow)
208
205
        #set title of progress window (same as gtk frontend)
209
206
        self.progress_bar.setWindowTitle(_('Installing'))
210
207
        #prevent progress bar from emitting reset on reaching max value (and auto closing)
212
209
        #force immediate showing, rather than waiting...
213
210
        self.progress_bar.setMinimumDuration(0)
214
211
        #must disconnect the canceled() SIGNAL, otherwise the progress bar is actually destroyed
215
 
        self.disconnect(self.progress_bar,SIGNAL('canceled()'),self.progress_bar.cancel)
 
212
        self.progress_bar.canceled.disconnect(self.progress_bar.cancel)
216
213
        #now we connect our own signal to display a warning dialog instead
217
 
        self.connect(self.progress_bar,SIGNAL('canceled()'),self.warning_dialog)
 
214
        self.progress_bar.canceled.connect(self.warning_dialog)
218
215
 
219
216
        #show the window
220
217
        self.__mainWindow.show()
235
232
        self.progress_bar.hide()
236
233
        if not message:
237
234
            message = _('Installation failed.')
238
 
        KMessageBox.error(self.__mainWindow, message)
 
235
        #KMessageBox.error(self.__mainWindow, message)
 
236
        QMessageBox.critical(self.__mainWindow, '', message)
239
237
        sys.exit(1)
240
238
 
241
239
    def add_timeout(self, interval, func, *args):
244
242
 
245
243
        # FIXME: now that we are part of a Qt object, we may be able to alter for builtin timers
246
244
        timer = QTimer()
247
 
        QObject.connect(timer,
248
 
            SIGNAL('timeout()'),
249
 
            lambda: self.__timeout_callback(func, *args))
 
245
        timer.timeout.connect(lambda: self.__timeout_callback(func, *args))
250
246
        timer.start(interval)
251
247
 
252
248
        return timer
267
263
        # the new_item lines should be auto triggered onChange to the
268
264
        # TreeWidget when new_item is appended.
269
265
        new_item.setText(0,target)
270
 
        new_item.setIcon(0,KIcon("drive-removable-media-usb-pendrive"))
 
266
        new_item.setIcon(0,QIcon.fromTheme("drive-removable-media-usb-pendrive"))
271
267
 
272
268
        item = self.__mainWindow.ui_dest_list.currentItem()
273
269
        if not item:
312
308
        # the new_item lines should be auto triggered onChange to the TreeWidget
313
309
        # when new_item is appended.
314
310
        new_item.setText(0,source)
315
 
        new_item.setIcon(0,KIcon("media-optical"))
 
311
        new_item.setIcon(0,QIcon.fromTheme("media-optical"))
316
312
 
317
313
        item = self.__mainWindow.ui_source_list.currentItem()
318
314
        if not item:
384
380
        for i in range(0,self.__mainWindow.ui_dest_list.topLevelItemCount()):
385
381
            item = self.__mainWindow.ui_dest_list.topLevelItem(i)
386
382
            if misc.text_type(item.data(0,Qt.UserRole)) == udi:
387
 
                self.__mainWindow.ui_dest_list.emit(
388
 
                    SIGNAL('itemChanged(item,0)'))
 
383
                # FIXME: pyqt5 entirely bypasses qt's signals and apparently fails
 
384
                #        to do so correctly so the following yields an error
 
385
                #        even though it should work just fine (i.e. the signal exists
 
386
                #        on the cpp side...
 
387
                self.__mainWindow.ui_dest_list.itemChanged.emit(item, 0)
389
388
                break
390
389
        # Update persistence maximum value.
391
390
        self.__mainWindow.ui_persist_frame.setEnabled(False)
449
448
    def add_file_source_dialog(self):
450
449
        self.__recently_added_image = None
451
450
        filename = ''
452
 
        filter = '*.iso|' + _('CD Images') + '\n*.img|' + _('Disk Images')
453
 
 
454
 
        # FIXME: should set the default path KUrl to users home dir...
455
 
        # This is all screwy as its run as root under kdesudo... Home = root and not user.. blarg!
456
 
        # Need to convert to plain string for backend to work
457
 
        filename = misc.text_type(KFileDialog.getOpenFileName(KUrl(KGlobalSettings.self().downloadPath()),
458
 
                                                              filter,
459
 
                                                              self.__mainWindow))
 
451
        # This here filter is for kfiledialog, no clue if it will ever make a return
 
452
        #filter = '*.iso|' + _('CD Images') + '\n*.img|' + _('Disk Images')
 
453
        filter = _('CD Images') + '(*.iso)' + ';;' + _('Disk Images') + '(*.img)'
 
454
 
 
455
        downloadPath = QStandardPaths.standardLocations(QStandardPaths.DownloadLocation)[0]
 
456
        openFileName = QFileDialog.getOpenFileName(self.__mainWindow,
 
457
                                                   '',
 
458
                                                   downloadPath,
 
459
                                                   filter)
 
460
        if openFileName:
 
461
            openFileName = openFileName[0]
 
462
        filename = misc.text_type(openFileName)
 
463
 
460
464
        if not filename:
461
465
            return
462
466
 
517
521
                 'computer with this device inserted to try or install '
518
522
                 'Ubuntu.')
519
523
 
520
 
        KMessageBox.information(self.__mainWindow, text)
 
524
        QMessageBox.information(self.__mainWindow, '', text)
521
525
        sys.exit(0)
522
526
 
523
527
    @thread_wrap
526
530
 
527
531
        caption = _('Retry?')
528
532
 
529
 
        res = KMessageBox.warningYesNo(self.__mainWindow,message,caption)
 
533
        #res = KMessageBox.warningYesNo(self.__mainWindow,message,caption)
 
534
        res = QMessageBox.warning(self.__mainWindow, caption, message,
 
535
                                  QMessageBox.Yes, QMessageBox.No)
530
536
 
531
 
        return res == KMessageBox.Yes
 
537
        #return res == KMessageBox.Yes
 
538
        return res == QMessageBox.Yes
532
539
 
533
540
    def notify(self,title):
534
 
        KMessageBox.sorry(self.__mainWindow,title)
 
541
        #KMessageBox.sorry(self.__mainWindow,title)
 
542
        QMessageBox.warning(self.__mainWindow, '', title)
535
543
 
536
544
    def warning_dialog(self):
537
545
        '''A warning dialog to show when progress dialog cancel is pressed'''
542
550
        #hide the progress bar - install will still continue in bg
543
551
        self.progress_bar.hide()
544
552
 
545
 
        res = KMessageBox.warningYesNo(self.__mainWindow,text,caption)
 
553
        #res = KMessageBox.warningYesNo(self.__mainWindow,text,caption)
 
554
        res = QMessageBox.warning(self.__mainWindow, caption, text,
 
555
                                  QMessageBox.Yes, QMessageBox.No)
546
556
 
547
 
        if res == KMessageBox.Yes:
 
557
        #if res == KMessageBox.Yes:
 
558
        if res == QMessageBox.Yes:
548
559
            self.quit()
549
560
 
550
561
        #user chose not to quit, so re-show progress bar
560
571
        self.__mainWindow.ui_format_dest.setEnabled(True)
561
572
        # TODO sort through error types (message.get_dbus_name()) in backend,
562
573
        # individual functions in frontend for each error type.
563
 
        KMessageBox.error(self.__mainWindow, str(message))
 
574
        #KMessageBox.error(self.__mainWindow, str(message))
 
575
        QMessageBox.critical(self.__mainWindow, '', str(message))
564
576
 
565
577
    def format_dest_clicked(self):
566
578
        item = self.__mainWindow.ui_dest_list.currentItem()
570
582
 
571
583
        text = _('Are you sure you want to erase the entire disk?')
572
584
 
573
 
        res = KMessageBox.warningYesNo(self.__mainWindow,text)
 
585
        #res = KMessageBox.warningYesNo(self.__mainWindow,text)
 
586
        res = QMessageBox.warning(self.__mainWindow, '', text,
 
587
                                  QMessageBox.Yes, QMessageBox.No)
574
588
 
575
 
        if res == KMessageBox.Yes:
 
589
        #if res == KMessageBox.Yes:
 
590
        if res == QMessageBox.Yes:
576
591
            self.__mainWindow.setCursor(Qt.BusyCursor)
577
592
            # Disable simultaneous format attempts.. let current finish first
578
593
            self.__mainWindow.ui_format_dest.setEnabled(False)