ProjectDjango/DjangoMigrationsListDialog.py

changeset 73
8a4ccc4f1359
parent 72
0f95786f7868
child 75
0165ce437462
diff -r 0f95786f7868 -r 8a4ccc4f1359 ProjectDjango/DjangoMigrationsListDialog.py
--- a/ProjectDjango/DjangoMigrationsListDialog.py	Sat Dec 17 19:07:02 2016 +0100
+++ b/ProjectDjango/DjangoMigrationsListDialog.py	Mon Dec 19 18:44:07 2016 +0100
@@ -13,9 +13,10 @@
 except NameError:
     pass
 
-from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer
+from PyQt5.QtCore import pyqtSlot, Qt, QProcess, QTimer, QPoint
 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \
-    QHeaderView, QTreeWidgetItem
+    QHeaderView, QTreeWidgetItem, QMenu, QAbstractItemView, QInputDialog, \
+    QLineEdit
 
 from E5Gui import E5MessageBox
 
@@ -31,12 +32,14 @@
     MigrationsListMode = "L"
     MigrationsPlanMode = "P"
     
-    def __init__(self, mode, parent=None):
+    def __init__(self, mode, django, parent=None):
         """
         Constructor
         
         @param parent reference to the parent widget
         @type QWidget
+        @param django reference to the Django project object
+        @type Project
         """
         super(DjangoMigrationsListDialog, self).__init__(parent)
         self.setupUi(self)
@@ -46,7 +49,15 @@
         
         self.ioEncoding = Preferences.getSystem("IOEncoding")
         
-        self.proc = None
+        self.proc = QProcess()
+        self.proc.finished.connect(self.__procFinished)
+        self.proc.readyReadStandardOutput.connect(self.__readStdout)
+        self.proc.readyReadStandardError.connect(self.__readStderr)
+        
+        self.__pyExe = ""
+        self.__sitePath = ""
+        
+        self.__django = django
         
         self.__mode = mode
         if self.__mode == DjangoMigrationsListDialog.MigrationsListMode:
@@ -54,12 +65,22 @@
             self.migrationsList.setHeaderLabels([
                 self.tr("Name"),
             ])
+            self.migrationsList.setSelectionMode(
+                QAbstractItemView.ExtendedSelection)
         else:
             self.setWindowTitle(self.tr("Migrations Plan"))
             self.migrationsList.setHeaderLabels([
                 self.tr("Migration"),
                 self.tr("Dependencies"),
             ])
+            self.migrationsList.setSelectionMode(
+                QAbstractItemView.SingleSelection)
+        
+        self.refreshButton = self.buttonBox.addButton(
+            self.tr("&Refresh"), QDialogButtonBox.ActionRole)
+        self.refreshButton.setToolTip(
+            self.tr("Press to refresh the list"))
+        self.refreshButton.setEnabled(False)
     
     @pyqtSlot(QAbstractButton)
     def on_buttonBox_clicked(self, button):
@@ -73,6 +94,8 @@
             self.close()
         elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
             self.__finish()
+        elif button == self.refreshButton:
+            self.on_refreshButton_clicked()
     
     def __finish(self):
         """
@@ -89,7 +112,7 @@
         self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
         self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
         
-        self.proc = None
+        self.refreshButton.setEnabled(True)
         
         self.__resizeColumns()
     
@@ -121,12 +144,11 @@
         @type str
         @return flag indicating a successful start of the process (boolean)
         """
-        self.errorGroup.hide()
+        self.__pyExe = pythonExecutable
+        self.__sitePath = sitePath
         
-        self.proc = QProcess()
-        self.proc.finished.connect(self.__procFinished)
-        self.proc.readyReadStandardOutput.connect(self.__readStdout)
-        self.proc.readyReadStandardError.connect(self.__readStderr)
+        self.errorGroup.hide()
+        self.migrationsList.clear()
         
         self.__lastTopItem = None
         
@@ -185,14 +207,17 @@
         else:
             # migration name
             line = line.strip()
-            applied = line[:3]
-            name = line[3:].strip()
-            if self.__lastTopItem:
-                itm = QTreeWidgetItem(self.__lastTopItem, [name])
-            else:
-                itm = QTreeWidgetItem(self.migrationsList, [name])
-            if applied[1] != " ":
-                itm.setCheckState(0, Qt.Checked)
+            if line.startswith("["):
+                applied = line[:3]
+                name = line[3:].strip()
+                if self.__lastTopItem:
+                    itm = QTreeWidgetItem(self.__lastTopItem, [name])
+                else:
+                    itm = QTreeWidgetItem(self.migrationsList, [name])
+                if applied[1] == " ":
+                    itm.setCheckState(0, Qt.Unchecked)
+                else:
+                    itm.setCheckState(0, Qt.Checked)
     
     def __createPlanItem(self, line):
         """
@@ -233,3 +258,120 @@
                     'replace')
             self.errors.insertPlainText(s)
             self.errors.ensureCursorVisible()
+    
+    @pyqtSlot()
+    def on_refreshButton_clicked(self):
+        """
+        Private slot to refresh the log.
+        """
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+        
+        self.refreshButton.setEnabled(False)
+        
+        self.start(self.__pyExe, self.__sitePath)
+    
+    @pyqtSlot(QPoint)
+    def on_migrationsList_customContextMenuRequested(self, pos):
+        """
+        Private slot to show the context menu.
+        
+        @param pos position the context menu was requested at
+        @type QPoint
+        """
+        menu = QMenu(self.migrationsList)
+        menu.addAction(self.tr("Apply All Migrations"),
+                       self.__applyAllMigrations)
+        
+        if self.__mode == DjangoMigrationsListDialog.MigrationsListMode:
+            selItems = self.migrationsList.selectedItems()
+            if len(selItems) > 0:
+                selApps = []
+                for itm in selItems:
+                    if itm.parent() is None:
+                        selApps.append(itm)
+                
+                menu.addAction(
+                    self.tr("Apply Selected Migrations"),
+                    self.__applyMigration).setEnabled(len(selItems) == 1)
+                menu.addAction(
+                    self.tr("Unapply Migrations"),
+                    self.__unapplyMigration).setEnabled(len(selApps) == 1)
+                menu.addSeparator()
+                menu.addAction(
+                    self.tr("Make Migrations"),
+                    self.__makeMigrations).setEnabled(len(selApps) > 0)
+                menu.addAction(
+                    self.tr("Make Migrations (dry-run)"),
+                    lambda: self.__makeMigrations(dryRun=True))\
+                .setEnabled(len(selApps) > 0)
+        else:
+            menu.addAction(self.tr("Apply Selected Migrations"),
+                           self.__applyMigration)
+        
+        menu.popup(self.migrationsList.mapToGlobal(pos))
+    
+    def __applyAllMigrations(self):
+        """
+        Private slot to apply all migrations.
+        """
+        self.__django.applyMigrations()
+        self.on_refreshButton_clicked()
+    
+    def __applyMigration(self):
+        """
+        Private slot to apply the selected migrations.
+        """
+        itm = self.migrationsList.selectedItems()[0]
+        if self.__mode == DjangoMigrationsListDialog.MigrationsListMode:
+            if itm.parent() is None:
+                # app item
+                app = itm.text(0)
+                migration = None
+            else:
+                migration = itm.text(0)
+                app = itm.parent().text(0)
+        else:
+            app, migration = itm.text(0).split(".", 1)
+        
+        self.__django.applyMigrations(app=app, migration=migration)
+        
+        self.on_refreshButton_clicked()
+    
+    def __unapplyMigration(self):
+        """
+        Private slot to unapply the selected migrations.
+        """
+        if self.__mode == DjangoMigrationsListDialog.MigrationsListMode:
+            itm = self.migrationsList.selectedItems()[0]
+            if itm.parent() is None:
+                # only valid for app entries
+                app = itm.text(0)
+                self.__django.applyMigrations(app=app, migration="zero")
+                
+                self.on_refreshButton_clicked()
+    
+    def __makeMigrations(self, dryRun=False):
+        """
+        Private slot to make migrations for the selected apps.
+        
+        @param dryRun dlag indicating a dry-run
+        @type bool
+        """
+        apps = []
+        for itm in self.migrationsList.selectedItems():
+            if itm.parent() is None:
+                apps.append(itm.text(0))
+        
+        if apps:
+            migration, ok = QInputDialog.getText(
+                self,
+                self.tr("Make Migrations"),
+                self.tr("Enter a name for the migrations (leave empty to"
+                        " use system supplied name):"),
+                QLineEdit.Normal)
+            if ok:
+                self.__django.makeMigrations(apps, migration, dryRun)
+            
+            self.on_refreshButton_clicked()

eric ide

mercurial