예제 #1
0
    def init_box_in_cell(self, row):
        try:
            key = self.tab_action.item(row, 0).text()
        except AttributeError:
            return
        commands = self.keys_map.get(key, False)
        if not key or not commands:
            return

        self.command_box.clear()
        if isinstance(commands, list):
            if self.CUSTOM_COMMAND_ROW not in commands:
                commands.insert(0, self.CUSTOM_COMMAND_ROW)
            try:
                custom_command = self.tab_action.item(row, 1).text()
                if custom_command not in commands:
                    commands.insert(1, custom_command)
            except AttributeError:
                pass
            finally:
                box = QComboBox()
                box.insertItems(0, commands)
                box.setCurrentIndex(1)
                self.tab_action.setCellWidget(row, 1, box)

                box.textActivated.connect(
                    lambda command: self.close_box_in_cell(row, command))
        else:
            self.tab_action.setItem(row, 1, QTableWidgetItem(commands))
예제 #2
0
 def createEditor(self, parent: PySide2.QtWidgets.QWidget, option: PySide2.QtWidgets.QStyleOptionViewItem,
                  index: QModelIndex) -> PySide2.QtWidgets.QWidget:
     item, column = index.model().item_and_column(index)
     vals, labels = item.values_choice(column)
     if vals:
         editor = QComboBox(parent)
         editor.insertItems(0, labels)
     else:
         editor = super().createEditor(parent, option, index)
     return editor
예제 #3
0
 def update_combobox(box: QComboBox, labels: List[str]) -> None:
     """Update the combobox menu."""
     box.blockSignals(True)
     box.clear()
     box.insertItems(0, labels)
     box.blockSignals(False)
예제 #4
0
파일: export.py 프로젝트: theqa0/Facepager
class ExportFileDialog(QFileDialog):
    """
    Create a custom Export-File Dialog with options like BOM etc.
    """
    def __init__(self, *args, **kwargs):
        super(ExportFileDialog, self).__init__(*args, **kwargs)

        self.mainWindow = self.parent()
        self.setWindowTitle("Export nodes to CSV")
        self.setAcceptMode(QFileDialog.AcceptSave)
        self.setOption(QFileDialog.DontUseNativeDialog)
        #self.setFilter("CSV Files (*.csv)")
        self.setDefaultSuffix("csv")

        self.optionBOM = QCheckBox("Use a BOM", self)
        self.optionBOM.setCheckState(Qt.CheckState.Checked)

        self.optionLinebreaks = QCheckBox("Remove line breaks", self)
        self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionSeparator = QComboBox(self)
        self.optionSeparator.insertItems(0, [";", "\\t", ","])
        self.optionSeparator.setEditable(True)

        #self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionWide = QCheckBox(
            "Convert to wide format (experimental feature)", self)
        self.optionWide.setCheckState(Qt.CheckState.Unchecked)

        # if none or all are selected, export all
        # if one or more are selected, export selective
        self.optionAll = QComboBox(self)
        self.optionAll.insertItems(0, [
            'All nodes (faster for large datasets, ordered by internal ID)',
            'Selected nodes (ordered like shown in nodes view)'
        ])
        if self.mainWindow.tree.noneOrAllSelected():
            self.optionAll.setCurrentIndex(0)
        else:
            self.optionAll.setCurrentIndex(1)

        layout = self.layout()
        row = layout.rowCount()
        layout.addWidget(QLabel('Options'), row, 0)

        options = QHBoxLayout()
        options.addWidget(self.optionBOM)
        options.addWidget(self.optionLinebreaks)
        options.addWidget(QLabel('Separator'))
        options.addWidget(self.optionSeparator)
        options.addStretch(1)

        layout.addLayout(options, row, 1, 1, 2)

        layout.addWidget(QLabel('Post processing'), row + 1, 0)
        layout.addWidget(self.optionWide, row + 1, 1, 1, 2)

        layout.addWidget(QLabel('Export mode'), row + 2, 0)
        layout.addWidget(self.optionAll, row + 2, 1, 1, 2)
        self.setLayout(layout)

        if self.exec_():

            if os.path.isfile(self.selectedFiles()[0]):
                os.remove(self.selectedFiles()[0])
            output = open(self.selectedFiles()[0],
                          'w',
                          newline='',
                          encoding='utf8')
            if self.optionBOM.isChecked() and not self.optionWide.isChecked():
                output.write('\ufeff')

            try:
                if self.optionAll.currentIndex() == 0:
                    self.exportAllNodes(output)
                else:
                    self.exportSelectedNodes(output)
            finally:
                output.close()

            if self.optionWide.isChecked():
                self.convertToWideFormat(self.selectedFiles()[0])

    def exportSelectedNodes(self, output):
        progress = ProgressBar("Exporting data...", self.mainWindow)

        #indexes = self.mainWindow.tree.selectionModel().selectedRows()
        #if child nodes should be exported as well, uncomment this line an comment the previous one
        indexes = self.mainWindow.tree.selectedIndexesAndChildren()
        indexes = list(indexes)
        progress.setMaximum(len(indexes))

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output,
                                delimiter=delimiter,
                                quotechar='"',
                                quoting=csv.QUOTE_ALL,
                                doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = [
                str(val)
                for val in self.mainWindow.tree.treemodel.getRowHeader()
            ]
            if self.optionLinebreaks.isChecked():
                row = [
                    val.replace('\n', ' ').replace('\r', ' ') for val in row
                ]

            writer.writerow(row)

            #rows
            for no in range(len(indexes)):
                if progress.wasCanceled:
                    break

                row = [
                    str(val) for val in
                    self.mainWindow.tree.treemodel.getRowData(indexes[no])
                ]
                if self.optionLinebreaks.isChecked():
                    row = [
                        val.replace('\n', ' ').replace('\r', ' ')
                        for val in row
                    ]

                writer.writerow(row)

                progress.step()

        finally:
            progress.close()

    def exportAllNodes(self, output):
        progress = ProgressBar("Exporting data...", self.mainWindow)
        progress.setMaximum(Node.query.count())

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output,
                                delimiter=delimiter,
                                quotechar='"',
                                quoting=csv.QUOTE_ALL,
                                doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = [
                "level", "id", "parent_id", "object_id", "object_type",
                "query_status", "query_time", "query_type"
            ]
            for key in self.mainWindow.tree.treemodel.customcolumns:
                row.append(key)
            if self.optionLinebreaks.isChecked():
                row = [
                    val.replace('\n', ' ').replace('\r', ' ') for val in row
                ]

            writer.writerow(row)

            #rows
            page = 0

            while True:
                allnodes = Node.query.offset(page * 5000).limit(5000)
                if allnodes.count() == 0:
                    break
                for node in allnodes:
                    if progress.wasCanceled:
                        break
                    row = [
                        node.level, node.id, node.parent_id, node.objectid,
                        node.objecttype, node.querystatus, node.querytime,
                        node.querytype
                    ]
                    for key in self.mainWindow.tree.treemodel.customcolumns:
                        row.append(node.getResponseValue(key))

                    if self.optionLinebreaks.isChecked():
                        row = [
                            str(val).replace('\n', ' ').replace('\r', ' ')
                            for val in row
                        ]

                    writer.writerow(row)
                    # step the Bar
                    progress.step()
                if progress.wasCanceled:
                    break
                else:
                    page += 1

        finally:
            progress.close()

    def convertToWideFormat(self, filename):
        progress = ProgressBar("Converting data...", self.mainWindow)
        try:
            #Separate levels
            def flattenTable(fulltable, levelcol, idcol, parentidcol,
                             countchildren, removeempty):
                fulltable[[levelcol]] = fulltable[[levelcol]].astype(int)

                levels = dict(list(fulltable.groupby(levelcol)))
                minlevel = fulltable.level.min()
                for level, data in sorted(levels.items()):
                    #First level is the starting point for the following merges
                    if level == minlevel:
                        #data = data[[idcol,'object_id','object_type']]
                        data = data.add_prefix('level_{}-'.format(level))
                        flattable = data
                    else:
                        #Aggregate object types and join them
                        for col_countchildren in countchildren:
                            children = data[parentidcol].groupby(
                                [data[parentidcol],
                                 data[col_countchildren]]).count()
                            children = children.unstack(col_countchildren)
                            children['total'] = children.sum(axis=1)
                            children = children.add_prefix(
                                'level_{}-children-{}-'.format(
                                    level - 1, col_countchildren))

                            leftkey = 'level_{}-id'.format(level - 1)
                            flattable = merge(flattable,
                                              children,
                                              how='left',
                                              left_on=leftkey,
                                              right_index=True)
                            flattable[children.columns.values.tolist(
                            )] = flattable[children.columns.values.tolist(
                            )].fillna(0).astype(int)

                        #Join data
                        data['childnumber'] = data.groupby(
                            parentidcol).cumcount()
                        leftkey = 'level_{}-{}'.format(level - 1, idcol)
                        rightkey = 'level_{}-{}'.format(level, parentidcol)
                        data = data.drop([levelcol], axis=1)
                        data = data.add_prefix('level_{}-'.format(level))
                        flattable = merge(flattable,
                                          data,
                                          how="outer",
                                          left_on=leftkey,
                                          right_on=rightkey)

                if removeempty:
                    flattable = flattable.dropna(axis=1, how='all')
                return flattable

            try:
                #delimiter
                delimiter = self.optionSeparator.currentText()
                delimiter = delimiter.encode('utf-8').decode('unicode_escape')

                #open
                data = read_csv(filename,
                                sep=delimiter,
                                encoding='utf-8',
                                dtype=str)

                #convert
                newdata = flattenTable(
                    data, 'level', 'id', 'parent_id',
                    ['object_type', 'query_status', 'query_type'], False)

                #save
                outfile = open(filename, 'w', newline='', encoding='utf8')
                try:
                    if self.optionBOM.isChecked():
                        outfile.write('\ufeff')  #UTF8 BOM
                    newdata.to_csv(outfile,
                                   sep=delimiter,
                                   index=False,
                                   encoding="utf-8")
                finally:
                    outfile.close()
            except Exception as e:
                self.mainWindow.logmessage(e)
        finally:
            progress.close()
예제 #5
0
파일: export.py 프로젝트: rsbekti/Facepager
class ExportFileDialog(QFileDialog):
    """
    Create a custom Export-File Dialog with options like BOM etc.
    """
    def __init__(self, *args, **kwargs):
        super(ExportFileDialog, self).__init__(*args, **kwargs)

        self.mainWindow = self.parent()
        self.setWindowTitle("Export nodes to CSV")
        self.setAcceptMode(QFileDialog.AcceptSave)
        self.setOption(QFileDialog.DontUseNativeDialog)
        #self.setFilter("CSV Files (*.csv)")
        self.setDefaultSuffix("csv")

        self.optionBOM = QCheckBox("Use a BOM", self)
        self.optionBOM.setCheckState(Qt.CheckState.Checked)

        self.optionLinebreaks = QCheckBox("Remove line breaks", self)
        self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionSeparator = QComboBox(self)
        self.optionSeparator.insertItems(0, [";", "\\t", ","])
        self.optionSeparator.setEditable(True)

        # if none or all are selected, export all
        # if one or more are selected, export selective
        self.optionAll = QComboBox(self)
        self.optionAll.insertItems(0, [
            'All nodes (faster for large datasets, ordered by internal ID)',
            'Selected nodes (ordered like shown in nodes view)'
        ])
        if self.mainWindow.tree.noneOrAllSelected():
            self.optionAll.setCurrentIndex(0)
        else:
            self.optionAll.setCurrentIndex(1)

        layout = self.layout()
        row = layout.rowCount()
        layout.addWidget(QLabel('Options'), row, 0)

        options = QHBoxLayout()
        options.addWidget(self.optionBOM)
        options.addWidget(self.optionLinebreaks)
        options.addWidget(QLabel('Separator'))
        options.addWidget(self.optionSeparator)
        options.addStretch(1)

        layout.addLayout(options, row, 1, 1, 2)

        layout.addWidget(QLabel('Export mode'), row + 2, 0)
        layout.addWidget(self.optionAll, row + 2, 1, 1, 2)
        self.setLayout(layout)

        if self.exec_():

            if os.path.isfile(self.selectedFiles()[0]):
                os.remove(self.selectedFiles()[0])
            output = open(self.selectedFiles()[0],
                          'w',
                          newline='',
                          encoding='utf8')
            if self.optionBOM.isChecked():
                output.write('\ufeff')

            try:
                if self.optionAll.currentIndex() == 0:
                    self.exportAllNodes(output)
                else:
                    self.exportSelectedNodes(output)
            finally:
                output.close()

    def exportSelectedNodes(self, output):
        progress = ProgressBar("Exporting data...", self.mainWindow)

        #indexes = self.mainWindow.tree.selectionModel().selectedRows()
        #if child nodes should be exported as well, uncomment this line an comment the previous one
        indexes = self.mainWindow.tree.selectedIndexesAndChildren()
        indexes = list(indexes)
        progress.setMaximum(len(indexes))

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output,
                                delimiter=delimiter,
                                quotechar='"',
                                quoting=csv.QUOTE_ALL,
                                doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = [
                str(val)
                for val in self.mainWindow.tree.treemodel.getRowHeader()
            ]
            if self.optionLinebreaks.isChecked():
                row = [
                    val.replace('\n', ' ').replace('\r', ' ') for val in row
                ]

            writer.writerow(row)

            #rows
            for no in range(len(indexes)):
                if progress.wasCanceled:
                    break

                row = [
                    str(val) for val in
                    self.mainWindow.tree.treemodel.getRowData(indexes[no])
                ]
                if self.optionLinebreaks.isChecked():
                    row = [
                        val.replace('\n', ' ').replace('\r', ' ')
                        for val in row
                    ]

                writer.writerow(row)

                progress.step()

        finally:
            progress.close()

    def exportAllNodes(self, output):
        progress = ProgressBar("Exporting data...", self.mainWindow)
        progress.setMaximum(Node.query.count())

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output,
                                delimiter=delimiter,
                                quotechar='"',
                                quoting=csv.QUOTE_ALL,
                                doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = [
                "level", "id", "parent_id", "object_id", "object_type",
                "query_status", "query_time", "query_type"
            ]
            for key in self.mainWindow.tree.treemodel.customcolumns:
                row.append(key)
            if self.optionLinebreaks.isChecked():
                row = [
                    val.replace('\n', ' ').replace('\r', ' ') for val in row
                ]

            writer.writerow(row)

            #rows
            page = 0

            while True:
                allnodes = Node.query.offset(page * 5000).limit(5000)
                if allnodes.count() == 0:
                    break
                for node in allnodes:
                    if progress.wasCanceled:
                        break
                    row = [
                        node.level, node.id, node.parent_id, node.objectid,
                        node.objecttype, node.querystatus, node.querytime,
                        node.querytype
                    ]
                    for key in self.mainWindow.tree.treemodel.customcolumns:
                        row.append(node.getResponseValue(key))

                    if self.optionLinebreaks.isChecked():
                        row = [
                            str(val).replace('\n', ' ').replace('\r', ' ')
                            for val in row
                        ]

                    writer.writerow(row)
                    # step the Bar
                    progress.step()
                if progress.wasCanceled:
                    break
                else:
                    page += 1

        finally:
            progress.close()
예제 #6
0
class MainWindow(QMainWindow):
    DIMENSION = 560
    placement_aleatoire = True
    nb_robots = 0

    def __init__(self, game):
        """
        La fenêtre principale est initialisée avec l'organisation suivante :

        +--------------------------------------------------------------------------+
        |              self.menu = self.menuBar()                                  |
        |                                                                          |
        +--------------------------------------------------------------------------+
        |       toolbar = QToolBar()  (déplacement/sélection des robots,           |
        |                     boutons annuler, indice et solution)                 |
        +------------------------layout0 = QHBoxLayout()---------------------------+
        |    layout2 = QHBoxLayout()                  +      moves_label           |
        | l                    +                      |                            |
        | a  grid_choice       |  nb_robots_choice    |     (affichage des         |
        +-y--------------------+----------------------+  L                         |
        | o                                           |  a  mouvements effectués)  |
        | u                                           |  y                         |
        | t                                           +--o-------------------------+
        | =          label = QLabel()                 |  u                         |
        | Q                                           |  t     tip_label           |
        | V          contient la grille de jeu        |  3                         |
        | B                                           |      (Affichage de l'indice|
        | o                                           |  =                         |
        | x                                           |      si demandé)           |
        | L                                           |  Q                         |
        | a                                           +--V+------------------------+
        | y                                           |  B     solution_label      |
        | o                                           |  o                         |
        | u                                           |  x   (Affichage de la      |
        | t                                           |                            |
        |                                             |      solution si demandée) |
        +---------------------------------------------+----------------------------+

        """

        super().__init__()
        self.game = game
        self.initial_game_state = self.game.get_state()
        self.number_moves = 0
        self.setWindowTitle("Robot Ricochet")
        self.resize(self.DIMENSION + 150, self.DIMENSION + 100)

        # label contient la grille de jeu
        self.label = QLabel()
        canvas = QPixmap(self.DIMENSION, self.DIMENSION)
        canvas.fill(Qt.white)
        self.label.setPixmap(canvas)

        # layout0 contient, à gauche, les barres d'outils et la grille,
        # et à droite, la liste des états et l'indice affiché par le solveur

        layout0 = QHBoxLayout()
        layout0.setContentsMargins(0, 0, 0, 0)
        layout0.setSpacing(0)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout2 = QHBoxLayout()

        # Choix de la grille
        self.choice_of_grid_menu()

        # choix du nombre de robots
        self.nb_robots_choice_menu()

        # CheckBox placement aléatoire
        widget3 = QCheckBox("Placement aléatoire des robots et de l'objectif")
        widget3.setCheckState(Qt.Checked)
        widget3.stateChanged.connect(self.placer_aleatoirement)

        # layout2 contient les 3 widgets horizontaux de choix de grille, robots et aléa
        layout2.addWidget(self.grid_choice)
        layout2.addWidget(self.nb_robots_choice)
        #layout2.addWidget(widget3)
        layout2.setContentsMargins(0, 0, 0, 0)
        layout2.setSpacing(0)
        widget2 = QWidget()
        widget2.setLayout(layout2)

        layout.addWidget(widget2)
        layout.addWidget(self.label)

        # liste des mouvement effectués, indice et solution:
        layout3 = QVBoxLayout()
        layout3.setContentsMargins(0, 0, 0, 0)
        layout3.setSpacing(0)

        self.moves_label = QLabel()
        self.print_moves_list()
        self.tip_label = QLabel()
        self.solution_label = QLabel()

        layout3.addWidget(self.moves_label)
        layout3.addWidget(self.tip_label)
        layout3.addWidget(self.solution_label)

        layout0.addLayout(layout)
        layout0.addLayout(layout3)
        widget = QWidget()
        widget.setLayout(layout0)
        self.setCentralWidget(widget)

        # Menu
        self.menu = self.menuBar()
        self.file_menu = self.menu.addMenu("File")
        self.help_menu = self.menu.addMenu("Aide et instructions")  # A faire
        self.size_fenetre = self.geometry()

        # Play QAction
        play_action = QAction("Réinitialiser !", self)
        play_action.triggered.connect(self.replay)
        self.file_menu.addAction(play_action)

        # Open_grid QAction
        open_grid_action = QAction("Ouvrir une grille", self)
        open_grid_action.setShortcut('Ctrl+O')
        open_grid_action.triggered.connect(self.open_grid)
        self.file_menu.addAction(open_grid_action)

        # Open_game QAction
        open_game_action = QAction("Ouvrir un jeu", self)
        open_game_action.triggered.connect(self.open_game)
        self.file_menu.addAction(open_game_action)

        # Save_grid QAction
        save_grid_action = QAction("Enregistrer cette grille", self)
        save_grid_action.triggered.connect(self.save_grid)
        self.file_menu.addAction(save_grid_action)

        # Save_game QAction
        save_game_action = QAction("Enregistrer ce jeu", self)
        save_game_action.triggered.connect(self.save_game)
        self.file_menu.addAction(save_game_action)

        # Exit QAction
        exit_action = QAction("Quitter", self)
        exit_action.setShortcut(QKeySequence.Quit)
        exit_action.triggered.connect(self.close)
        self.file_menu.addAction(exit_action)

        # Help QAction
        help_action = QAction("Aide", self)
        help_action.triggered.connect(self.help)
        self.help_menu.addAction(help_action)
        self.toolbar_menus()

        #Le robot rouge est sélectionné par défaut
        self.selected_robot = 'R'

        self.draw_robots_and_goal()

    def replay(self):
        """ on remet l'état initial du jeu """
        self.game.set_state(self.initial_game_state)
        self.game.moves_list = []
        self.game.states_list = deque([self.game.state_start], maxlen=100)
        self.unprint_moves_list()
        self.number_moves = 0
        self.draw_robots_and_goal()

    def help(self):
        """ Ouvre une fenêtre d'aide"""
        self.help_windows = Help_window()
        self.help_windows.exec_()

    def toolbar_menus(self):
        """ Affiche la barre d'icônes permettant de diriger les robots et de les sélectionner"""

        # Toolbar
        toolbar = QToolBar("Game toolbar")
        self.addToolBar(toolbar)

        # Flèche gauche
        button_West = QAction(QIcon(ICON_PATH + "arrow-180.png"), "West", self)
        button_West.setStatusTip("Aller à gauche")
        button_West.triggered.connect(self.onButtonWestClick)
        button_West.setCheckable(False)
        button_West.setShortcut(QKeySequence("Left"))
        toolbar.addAction(button_West)

        # Flèche droite
        button_East = QAction(QIcon(ICON_PATH + "arrow.png"), "Est", self)
        button_East.setStatusTip("Aller à droite")
        button_East.triggered.connect(self.onButtonEastClick)
        button_East.setCheckable(False)
        button_East.setShortcut(QKeySequence("Right"))
        toolbar.addAction(button_East)

        # Flèche Haut
        button_North = QAction(QIcon(ICON_PATH + "arrow-090.png"), "North",
                               self)
        button_North.setStatusTip("Aller vers le haut")
        button_North.triggered.connect(self.onButtonNorthClick)
        button_North.setCheckable(False)
        button_North.setShortcut(QKeySequence("Up"))
        toolbar.addAction(button_North)

        # Flèche Bas
        button_South = QAction(QIcon(ICON_PATH + "arrow-270.png"), "South",
                               self)
        button_South.setStatusTip("Aller vers le Bas")
        button_South.triggered.connect(self.onButtonSouthClick)
        button_South.setCheckable(False)
        button_South.setShortcut(QKeySequence("Down"))
        toolbar.addAction(button_South)

        # Selection robot actif
        button_Red = QPushButton("&Red")
        button_Red.setIcon(QIcon(ICON_PATH + "icon_R.png"))
        button_Red.setAutoExclusive(True)
        button_Red.setCheckable(True)
        button_Red.setShortcut(QKeySequence("R"))
        button_Red.toggled.connect(self.onButtonRedClick)

        button_Green = QPushButton("&Green")
        button_Green.setIcon(QIcon(ICON_PATH + "icon_G.png"))
        button_Green.setAutoExclusive(True)
        button_Green.setCheckable(True)
        button_Green.setShortcut(QKeySequence("G"))
        button_Green.toggled.connect(self.onButtonGreenClick)

        button_Blue = QPushButton("&Blue")
        button_Blue.setIcon(QIcon(ICON_PATH + "icon_B.png"))
        button_Blue.setAutoExclusive(True)
        button_Blue.setCheckable(True)
        button_Blue.setShortcut(QKeySequence("B"))
        button_Blue.toggled.connect(self.onButtonBlueClick)

        button_Yellow = QPushButton("&Yellow")
        button_Yellow.setIcon(QIcon(ICON_PATH + "icon_Y.png"))
        button_Yellow.setAutoExclusive(True)
        button_Yellow.setCheckable(True)
        button_Yellow.setShortcut(QKeySequence("Y"))
        button_Yellow.toggled.connect(self.onButtonYellowClick)

        # Boutton d'annulation (revient en arrière d'un coup)
        button_undo = QPushButton("&Undo")
        button_undo.setIcon(QIcon(ICON_PATH + "undo.jpg"))
        button_undo.setAutoExclusive(False)
        button_undo.setCheckable(False)
        button_undo.setShortcut(QKeySequence("U"))
        button_undo.clicked.connect(self.onButtonUndoClick)

        # Boutton d'indice : lance le solveur pour donner l'indice du prochain coup à effectuer
        button_tip = QPushButton("&Tip")
        button_tip.setIcon(QIcon(ICON_PATH + "icon_tip.png"))
        button_tip.setAutoExclusive(False)
        button_tip.setCheckable(False)
        button_tip.setShortcut(QKeySequence("T"))
        button_tip.clicked.connect(self.onButtonTipClick)

        # Boutton Solution : lance le solveur pour afficher une liste d'actions à effectuer pour résoudre le jeu
        button_solution = QPushButton("&Solution")
        button_solution.setIcon(QIcon(ICON_PATH + "icon_solution.png"))
        button_solution.setAutoExclusive(False)
        button_solution.setCheckable(False)
        button_solution.setShortcut(QKeySequence("S"))
        button_solution.clicked.connect(self.onButtonSolutionClick)

        toolbar.addWidget(button_Red)
        toolbar.addWidget(button_Green)
        toolbar.addWidget(button_Blue)
        toolbar.addWidget(button_Yellow)
        toolbar.addWidget(button_undo)
        toolbar.addWidget(button_tip)
        toolbar.addWidget(button_solution)

    def open_grid(self):
        """ Ouvre une boîte de dialogue permettant de charger une grille existante sur le disque dur"""

        filename, filter = QFileDialog.getOpenFileName(
            self, 'selectionner un fichier contenant une grille', './grids',
            '*.json')
        board, = Board.load_from_json(filename)
        self.game.add_board(board)
        self.number_moves = 0
        self.group = Robot_group()
        self.game = Game(self.game.board, self.group, self.game.goal)
        self.unprint_moves_list()
        self.draw_grid()

    def open_game(self):
        """ Ouvre une boîte de dialogue permettant de charger un jeu existant sur le disque dur"""

        filename, filter = QFileDialog.getOpenFileName(
            self, 'selectionner un fichier contenant un jeu', './games',
            '*.json')
        self.game = Game.load_from_json(filename)
        self.initial_game_state = self.game.get_state()
        self.number_moves = 0
        self.unprint_moves_list()
        self.draw_robots_and_goal()

    def save_grid(self):
        """ Ouvre une boîte de dialogue permettant d'enregistrer la grille affichée sur le disque dur"""

        filename, _ = QFileDialog.getSaveFileName(
            self,
            "Save Grid As",
            "",
            "JSON (*.JSON *.json);;"
            "All files(*.*)",
        )
        if filename:
            self.game.board.save_as_json(filename)

    def save_game(self):
        """ Ouvre une boîte de dialogue permettant d'enregistrer le jeu actuel sur le disque dur
            Si le joueur entre ou sélectionne un nom de fichier, le eju est sauvegardé dans ce fichier
            """

        filename, _ = QFileDialog.getSaveFileName(
            self,
            "Save game As",
            "",
            "JSON (*.JSON *.json);;"
            "All files(*.*)",
        )
        if filename:
            self.game.save_to_json(filename)

    def print_moves_list(self):
        """ Affichage de la liste des mouvements effectués dans le label "moves_label" """

        self.moves_label.setText("Mouvements effectués : \n" +
                                 str(self.game.moves_list).replace(', ', '\n'))
        self.moves_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def unprint_moves_list(self):
        """ réinitialisation du label "moves_label" pour cacher la liste des mouvements effectués. """
        self.moves_label.setText(" ")
        self.moves_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def print_tip(self):
        """ Affichage du conseil généré par le solveur  dans le label "tip_label" """

        self.tip_label.setText("Et si vous essayiez ce mouvement : \n" +
                               str(self.tip) + " ?")
        self.tip_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def unprint_tip(self):
        """ réinitialisation du label "tip_label" pour cacher le conseil généré par le solveur. """
        self.tip_label.setText(" ")
        self.tip_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        self.solution_label.setText(" ")

    def choice_of_grid_menu(self):

        self.grid_choice = QComboBox()
        self.grid_choice.insertItems(
            0, ("Grille 6x6", "Grille 8x8", "Grille 10x10", "Grille 12x12",
                "Grille 14x14", "Grille 16x16", "Grille aléatoire 16x16"))
        self.grid_choice.setGeometry(0, 0, 180, 40)
        self.grid_choice.activated.connect(self.choix_grille)

    def choix_grille(self, i):
        """
        Lors du choix d'une nouvelle grille, le jeu est réinitialisé et redessiné, les robots et l'objectif sont masqués.
        """

        # pour ouvrir les vieux .txt
        # name_grid = './test' + str(i + 1) + '.txt'
        # fd = open(name_grid,'r')
        # A = Board.load_from_json(fd)

        if i == 0:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 6x6.json')
        elif i == 1:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 8x8.json')
        elif i == 2:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 10x10.json')
        elif i == 3:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 12x12.json')
        elif i == 4:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 14x14.json')
        elif i == 5:
            A, = Board.load_from_json(GRIDS_PATH + 'grid 16x16.json')
        else:
            # Pour ouvrir une grille aléatoire classique
            A = Board.new_classic()

        self.game.add_board(A)
        self.number_moves = 0
        self.group = Robot_group()
        self.game = Game(self.game.board, self.group, self.game.goal)
        self.draw_grid()

        # choix du nombre de robots
    def nb_robots_choice_menu(self):
        self.nb_robots_choice = QComboBox()
        self.nb_robots_choice.insertItems(
            0, ("1 robot", "2 robots", "3 robots", "4 robots"))
        self.nb_robots_choice.setGeometry(0, 0, 40, 40)
        self.nb_robots_choice.activated.connect(self.choix_nb_robots)

    def choix_nb_robots(self, i):
        """
        Les robots et l'objectif sont placés aléatoirement. L'extension
        """

        self.group = Robot_group()
        self.game = Game(self.game.board, self.group, self.game.goal)

        self.nb_robots = i + 1

        robots_pos = [0] * self.nb_robots
        robots_list = [0] * self.nb_robots
        robots_colors = [i for i in RColors]
        if self.placement_aleatoire:

            for i in range(self.nb_robots):
                x = randint(0, self.game.board.width - 1)
                y = randint(0, self.game.board.height - 1)
                while ((x, y) in robots_pos):
                    x = randint(0, self.game.board.width - 1)
                    y = randint(0, self.game.board.height - 1)
                robots_pos[i] = (x, y)
                robots_list[i] = Robot(self.game.robots, robots_colors[i],
                                       (x, y))

            x = randint(0, self.game.board.width - 1)
            y = randint(0, self.game.board.height - 1)
            goal = Goal(RColors(randint(1, self.nb_robots)), (x, y))
            self.game = Game(self.game.board, self.group, self.game.goal)
            self.game.add_goal(goal)
            self.initial_game_state = self.game.get_state()
            self.draw_robots_and_goal()

        else:
            fp = open(GAMES_PATH + DEFAULT_GAME, 'r')
            self.game = Game.load_from_json(fp)
            fp.close()

    def draw_grid(self):
        """
        Dessine la grille de jeu en juxtaposant les images contenant chaque case. Chaque image est redimensionnée et ajustée à la taille de la grille.
        """
        painter = QPainter(self.label.pixmap())
        names = [
            "Empty", "N", "E", "EN", "S", "NS", "ES", "ENS", "W", "NW", "EW",
            "ENW", "SW", "NSW", "ESW", "ENSW"
        ]
        images = [
            QPixmap(IMAGES_PATH + name + ".bmp", format="bmp")
            for name in names
        ]

        for x in range(0, self.game.board.width):
            for y in range(0, self.game.board.height):
                painter.drawPixmap(
                    QPoint(self.DIMENSION / self.game.board.height * y,
                           self.DIMENSION / self.game.board.width * x),
                    images[int(str(self.game.board.grid[x][y]))].scaled(
                        self.DIMENSION / self.game.board.width,
                        self.DIMENSION / self.game.board.height))

        self.update()
        painter.end()

    def draw_robots_and_goal(self):
        self.draw_grid()

        painter = QPainter(self.label.pixmap())

        goal_img_name = ICON_PATH + "/goal_" + str(
            self.game.goal.color) + ".png"
        painter.drawPixmap(
            QPoint(
                self.DIMENSION / self.game.board.height *
                self.game.goal.position[1], self.DIMENSION /
                self.game.board.width * self.game.goal.position[0]),
            QPixmap(goal_img_name, format="png").scaled(
                self.DIMENSION / self.game.board.width * 0.9,
                self.DIMENSION / self.game.board.height * 0.9))

        images = [
            QPixmap(ICON_PATH + "robot_" + str(color) + ".png", format="png")
            for color in self.game.color_keys
        ]

        for i, robot in enumerate(self.game.robots):

            painter.drawPixmap(
                QPoint(
                    self.DIMENSION / self.game.board.height *
                    self.game.robots[robot].position[1],
                    self.DIMENSION / self.game.board.width *
                    self.game.robots[robot].position[0]),
                images[i].scaled(self.DIMENSION / self.game.board.width * 0.8,
                                 self.DIMENSION / self.game.board.height))

        self.update()
        painter.end()

    def onButtonEastClick(self, s):
        self.game.do_action(self.selected_robot + 'E')

        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def onButtonWestClick(self, s):
        self.game.do_action(self.selected_robot + 'W')
        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def onButtonNorthClick(self, s):
        self.game.do_action(self.selected_robot + 'N')
        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def onButtonSouthClick(self, s):
        self.game.do_action(self.selected_robot + 'S')
        self.draw_robots_and_goal()
        self.number_moves += 1
        self.print_moves_list()
        self.unprint_tip()
        if self.game.is_won():
            self.game_is_won()

    def placer_aleatoirement(self):
        """ inverse la sélection de la checkBox """
        self.placement_aleatoire = not (self.placement_aleatoire)

    def onButtonRedClick(self, s):
        if s:
            self.selected_robot = 'R'

    def onButtonGreenClick(self, s):
        if s:
            self.selected_robot = 'G'

    def onButtonBlueClick(self, s):
        if s:
            self.selected_robot = 'B'

    def onButtonYellowClick(self, s):
        if s:
            self.selected_robot = 'Y'

    def onButtonUndoClick(self, s):
        """ Annule le dernier coup effectué """
        if self.number_moves != 0:
            self.game.undo()
            self.number_moves -= 1
            self.print_moves_list()
            self.unprint_tip()
            self.draw_robots_and_goal()

    def solve(self):
        """tip_game contient une copie du jeu courant, pour l'utiliser par le solveur"""

        self.game.save_to_json('tip_game.json')
        self.tip_game = Game.load_from_json('tip_game.json')
        return (solveur(self.tip_game).find_solution())

    def onButtonTipClick(self, s):
        """ La solution renvoyée par le solveur est de la forme (True/False, liste d'actions à effectuer).
        On récupère ici la première action."""
        self.tip = self.solve()[1][0]
        self.print_tip()

    def onButtonSolutionClick(self, s):
        self.solution = self.solve()[1]
        self.solution_label.setText(
            "Pour gagner, vous auriez pu effectuer cette suite de mouvements : \n"
            + str(self.solution) + ".")
        self.solution_label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)

    def game_is_won(self):
        """ Fonction lancée quand l'objectif est atteint. On génère une fonction exit_windows dont le code de retour 1, 2 ou 3 valide le choix :
        1 : replay : on remet l'état initial du jeu
        2 : new game : on choisit une grille aleatoire
        3 : exit : on quitte le jeu.
        """
        self.exit_windows = Exit_window(self.number_moves)

        self.exit_windows.exec_()

        if self.exit_windows.retStatus == 1:  #replay : on remet l'état initial du jeu
            self.replay()

        elif self.exit_windows.retStatus == 2:  #new game : on choisit une grille aleatoire
            self.choix_grille(1)
            self.choix_nb_robots(3)
            self.unprint_moves_list()

        elif self.exit_windows.retStatus == 3:  #exit : on quitte le jeu
            exit()
예제 #7
0
class ExportFileDialog(QFileDialog):
    """
    Create a custom Export-File Dialog with options like BOM etc.
    """
    def __init__(self, *args, **kwargs):
        super(ExportFileDialog, self).__init__(*args, **kwargs)

        self.mainWindow = self.parent()
        self.setWindowTitle("Export nodes to CSV")
        self.setAcceptMode(QFileDialog.AcceptSave)
        self.setOption(QFileDialog.DontUseNativeDialog)
        #self.setFilter("CSV Files (*.csv)")
        self.setDefaultSuffix("csv")

        self.optionBOM = QCheckBox("Use a BOM", self)
        self.optionBOM.setCheckState(Qt.CheckState.Checked)

        self.optionLinebreaks = QCheckBox("Remove line breaks", self)
        self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionSeparator = QComboBox(self)
        self.optionSeparator.insertItems(0, [";", "\\t", ","])
        self.optionSeparator.setEditable(True)

        # if none or all are selected, export all
        # if one or more are selected, export selective
        self.optionAll = QComboBox(self)
        self.optionAll.insertItems(0, [
            'All nodes (faster for large datasets, ordered by internal ID)',
            'Selected nodes (ordered like shown in nodes view)'
        ])
        if self.mainWindow.tree.noneOrAllSelected():
            self.optionAll.setCurrentIndex(0)
        else:
            self.optionAll.setCurrentIndex(1)

        layout = self.layout()
        row = layout.rowCount()
        layout.addWidget(QLabel('Options'), row, 0)

        options = QHBoxLayout()
        options.addWidget(self.optionBOM)
        options.addWidget(self.optionLinebreaks)
        options.addWidget(QLabel('Separator'))
        options.addWidget(self.optionSeparator)
        options.addStretch(1)

        layout.addLayout(options, row, 1, 1, 2)

        layout.addWidget(QLabel('Export mode'), row + 2, 0)
        layout.addWidget(self.optionAll, row + 2, 1, 1, 2)
        self.setLayout(layout)

        dbfilename = self.mainWindow.database.filename
        #self.setDirectory(os.path.dirname(dbfilename))
        filename, ext = os.path.splitext(dbfilename)
        self.selectFile(filename + '.csv')

        # if not os.path.exists(dbfilename):
        #     dbfilename = self.mainWindow.settings.value("lastpath", os.path.expanduser("~"))
        # if not os.path.exists(dbfilename):
        #     dbfilename = os.path.expanduser("~")

        if self.exec_():
            try:
                if os.path.isfile(self.selectedFiles()[0]):
                    os.remove(self.selectedFiles()[0])
            except Exception as e:
                QMessageBox.information(self, "Facepager",
                                        "Could not overwrite file:" + str(e))
                return False

            output = open(self.selectedFiles()[0],
                          'w',
                          newline='',
                          encoding='utf8')
            try:
                if self.optionBOM.isChecked():
                    output.write('\ufeff')

                if self.optionAll.currentIndex() == 0:
                    self.exportAllNodes(output)
                else:
                    self.exportSelectedNodes(output)
            finally:
                output.close()

    def exportSelectedNodes(self, output):
        progress = ProgressBar("Exporting data...", self.mainWindow)

        #indexes = self.mainWindow.tree.selectionModel().selectedRows()
        #if child nodes should be exported as well, uncomment this line an comment the previous one
        indexes = self.mainWindow.tree.selectedIndexesAndChildren()
        indexes = list(indexes)
        progress.setMaximum(len(indexes))

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output,
                                delimiter=delimiter,
                                quotechar='"',
                                quoting=csv.QUOTE_ALL,
                                doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = [
                str(val)
                for val in self.mainWindow.tree.treemodel.getRowHeader()
            ]
            if self.optionLinebreaks.isChecked():
                row = [
                    val.replace('\n', ' ').replace('\r', ' ') for val in row
                ]
            row = ['path'] + row
            writer.writerow(row)

            #rows
            path = []
            for index in indexes:
                if progress.wasCanceled:
                    break

                # data
                rowdata = self.mainWindow.tree.treemodel.getRowData(index)

                # path of parents (#2=level;#3=object ID)
                while rowdata[2] < len(path):
                    path.pop()
                path.append(rowdata[3])

                # values
                row = [str(val) for val in rowdata]
                row = ["/".join(path)] + row
                if self.optionLinebreaks.isChecked():
                    row = [
                        val.replace('\n', ' ').replace('\r', ' ')
                        for val in row
                    ]

                writer.writerow(row)

                progress.step()

        finally:
            progress.close()

    def exportAllNodes(self, output):
        progress = ProgressBar("Exporting data...", self.mainWindow)
        progress.setMaximum(Node.query.count())

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output,
                                delimiter=delimiter,
                                quotechar='"',
                                quoting=csv.QUOTE_ALL,
                                doublequote=True,
                                lineterminator='\r\n')

            # Headers
            row = [
                "level", "id", "parent_id", "object_id", "object_type",
                "object_key", "query_status", "query_time", "query_type"
            ]
            for key in extractNames(
                    self.mainWindow.tree.treemodel.customcolumns):
                row.append(key)
            if self.optionLinebreaks.isChecked():
                row = [
                    val.replace('\n', ' ').replace('\r', ' ') for val in row
                ]
            writer.writerow(row)

            # Rows
            page = 0
            while not progress.wasCanceled:
                allnodes = Node.query.offset(page * 5000).limit(5000)
                if allnodes.count() == 0:
                    break

                for node in allnodes:
                    if progress.wasCanceled:
                        break

                    row = [
                        node.level, node.id, node.parent_id, node.objectid,
                        node.objecttype,
                        getDictValue(node.queryparams, 'nodedata'),
                        node.querystatus, node.querytime, node.querytype
                    ]
                    for key in self.mainWindow.tree.treemodel.customcolumns:
                        row.append(node.getResponseValue(key)[1])

                    if self.optionLinebreaks.isChecked():
                        row = [
                            str(val).replace('\n', ' ').replace('\r', ' ')
                            for val in row
                        ]

                    writer.writerow(row)

                    # Step the bar
                    progress.step()

                page += 1

        finally:
            progress.close()
예제 #8
0
파일: export.py 프로젝트: strohne/Facepager
class ExportFileDialog(QFileDialog):
    """
    Create a custom Export-File Dialog with options like BOM etc.
    """

    def __init__(self,*args,**kwargs):
        super(ExportFileDialog,self).__init__(*args,**kwargs)

        self.mainWindow = self.parent()
        self.setWindowTitle("Export nodes to CSV")
        self.setAcceptMode(QFileDialog.AcceptSave)
        self.setOption(QFileDialog.DontUseNativeDialog)
        #self.setFilter("CSV Files (*.csv)")
        self.setDefaultSuffix("csv")

        self.optionBOM = QCheckBox("Use a BOM",self)
        self.optionBOM.setCheckState(Qt.CheckState.Checked)

        self.optionLinebreaks = QCheckBox("Remove line breaks",self)
        self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionSeparator = QComboBox(self)
        self.optionSeparator.insertItems(0, [";","\\t",","])
        self.optionSeparator.setEditable(True)

        #self.optionLinebreaks.setCheckState(Qt.CheckState.Checked)

        self.optionWide = QCheckBox("Convert to wide format (experimental feature)",self)
        self.optionWide.setCheckState(Qt.CheckState.Unchecked)

        # if none or all are selected, export all
        # if one or more are selected, export selective
        self.optionAll = QComboBox(self)
        self.optionAll.insertItems(0, ['All nodes (faster for large datasets, ordered by internal ID)','Selected nodes (ordered like shown in nodes view)'])
        if self.mainWindow.tree.noneOrAllSelected():
            self.optionAll.setCurrentIndex(0)
        else:
            self.optionAll.setCurrentIndex(1)

        layout = self.layout()
        row = layout.rowCount()
        layout.addWidget(QLabel('Options'),row,0)

        options = QHBoxLayout()
        options.addWidget(self.optionBOM)
        options.addWidget(self.optionLinebreaks)
        options.addWidget(QLabel('Separator'))
        options.addWidget(self.optionSeparator)
        options.addStretch(1)

        layout.addLayout(options,row,1,1,2)

        layout.addWidget(QLabel('Post processing'),row+1,0)
        layout.addWidget(self.optionWide,row+1,1,1,2)

        layout.addWidget(QLabel('Export mode'),row+2,0)
        layout.addWidget(self.optionAll,row+2,1,1,2)
        self.setLayout(layout)

        if self.exec_():

            if os.path.isfile(self.selectedFiles()[0]):
                os.remove(self.selectedFiles()[0])
            output = open(self.selectedFiles()[0], 'w', newline='', encoding='utf8')
            if self.optionBOM.isChecked() and not self.optionWide.isChecked():
                output.write('\ufeff')

            try:
                if self.optionAll.currentIndex() == 0:
                    self.exportAllNodes(output)
                else:
                    self.exportSelectedNodes(output)
            finally:
                output.close()

            if self.optionWide.isChecked():
                self.convertToWideFormat(self.selectedFiles()[0])


    def exportSelectedNodes(self,output):
        progress = ProgressBar("Exporting data...", self.mainWindow)

        #indexes = self.mainWindow.tree.selectionModel().selectedRows()
        #if child nodes should be exported as well, uncomment this line an comment the previous one
        indexes = self.mainWindow.tree.selectedIndexesAndChildren()
        progress.setMaximum(len(indexes))

        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output, delimiter=delimiter, quotechar='"', quoting=csv.QUOTE_ALL, doublequote=True,
                                lineterminator='\r\n')


            #headers
            row = [str(val) for val in self.mainWindow.tree.treemodel.getRowHeader()]
            if self.optionLinebreaks.isChecked():
                row = [val.replace('\n', ' ').replace('\r',' ') for val in row]

            writer.writerow(row)

            #rows
            for no in range(len(indexes)):
                if progress.wasCanceled:
                    break

                row = [str(val) for val in self.mainWindow.tree.treemodel.getRowData(indexes[no])]
                if self.optionLinebreaks.isChecked():
                    row = [val.replace('\n', ' ').replace('\r',' ') for val in row]

                writer.writerow(row)

                progress.step()

        finally:
            progress.close()


    def exportAllNodes(self,output):
        progress = ProgressBar("Exporting data...", self.mainWindow)
        progress.setMaximum(Node.query.count())


        try:
            delimiter = self.optionSeparator.currentText()
            delimiter = delimiter.encode('utf-8').decode('unicode_escape')
            writer = csv.writer(output, delimiter=delimiter, quotechar='"', quoting=csv.QUOTE_ALL, doublequote=True,
                                lineterminator='\r\n')

            #headers
            row = ["level", "id", "parent_id", "object_id", "object_type", "query_status", "query_time",
                   "query_type"]
            for key in self.mainWindow.tree.treemodel.customcolumns:
                row.append(key)
            if self.optionLinebreaks.isChecked():
                row = [val.replace('\n', ' ').replace('\r',' ') for val in row]

            writer.writerow(row)

            #rows
            page = 0

            while True:
                allnodes = Node.query.offset(page * 5000).limit(5000)
                if allnodes.count() == 0:
                    break
                for node in allnodes:
                    if progress.wasCanceled:
                        break
                    row = [node.level, node.id, node.parent_id, node.objectid, node.objecttype,
                           node.querystatus, node.querytime, node.querytype]
                    for key in self.mainWindow.tree.treemodel.customcolumns:
                        row.append(node.getResponseValue(key))

                    if self.optionLinebreaks.isChecked():
                        row = [str(val).replace('\n', ' ').replace('\r',' ') for val in row]

                    writer.writerow(row)
                    # step the Bar
                    progress.step()
                if progress.wasCanceled:
                    break
                else:
                    page += 1

        finally:
            progress.close()

    def convertToWideFormat(self,filename):
        progress = ProgressBar("Converting data...", self.mainWindow)
        try:
            #Separate levels
            def flattenTable(fulltable,levelcol,idcol,parentidcol,countchildren,removeempty):
                fulltable[[levelcol]] = fulltable[[levelcol]].astype(int)

                levels = dict(list(fulltable.groupby(levelcol)))
                minlevel = fulltable.level.min()
                for level, data in sorted(levels.items()):
                    #First level is the starting point for the following merges
                    if level == minlevel:
                        #data = data[[idcol,'object_id','object_type']]
                        data = data.add_prefix('level_{}-'.format(level))
                        flattable = data
                    else:
                        #Aggregate object types and join them
                        for col_countchildren in countchildren:
                            children = data[parentidcol].groupby([data[parentidcol],data[col_countchildren]]).count()
                            children = children.unstack(col_countchildren)
                            children['total'] = children.sum(axis=1)
                            children = children.add_prefix('level_{}-children-{}-'.format(level-1,col_countchildren))

                            leftkey = 'level_{}-id'.format(level-1)
                            flattable = merge(flattable,children,how='left',left_on=leftkey,right_index=True)
                            flattable[children.columns.values.tolist()] = flattable[children.columns.values.tolist()].fillna(0).astype(int)

                        #Join data
                        data['childnumber'] = data.groupby(parentidcol).cumcount()
                        leftkey = 'level_{}-{}'.format(level-1,idcol)
                        rightkey = 'level_{}-{}'.format(level,parentidcol)
                        data = data.drop([levelcol],axis=1)
                        data = data.add_prefix('level_{}-'.format(level))
                        flattable = merge(flattable,data,how="outer",left_on=leftkey,right_on=rightkey)

                if removeempty:
                    flattable = flattable.dropna(axis=1,how='all')
                return flattable

            try:
                #delimiter
                delimiter = self.optionSeparator.currentText()
                delimiter = delimiter.encode('utf-8').decode('unicode_escape')

                #open
                data = read_csv(filename, sep=delimiter,encoding='utf-8',dtype=str)

                #convert
                newdata = flattenTable(data,'level','id','parent_id',['object_type','query_status','query_type'],False)


                #save
                outfile = open(filename, 'w',newline='',encoding='utf8')
                try:
                    if self.optionBOM.isChecked():
                        outfile.write('\ufeff') #UTF8 BOM
                    newdata.to_csv(outfile,sep=delimiter,index=False,encoding="utf-8")
                finally:
                    outfile.close()
            except Exception as e:
                self.mainWindow.logmessage(e)
        finally:
            progress.close()
예제 #9
0
class EditCommentBankWindow(QMainWindow):
    def __init__(self, subject_name):
        QMainWindow.__init__(self)
        self.setWindowTitle("Edit Comment Bank: {} - {} {}".format(
            subject_name, config.APP_NAME, config.APP_VERSION))
        self.setMinimumWidth(1200)
        self.setStyleSheet(config.STYLESHEET)

        self.subject = could_try_harder.load(subject_name)
        self.saved_list = could_try_harder.get_saved_list()

        # Widgets
        self.intro_comment_label = QLabel("Introductory Comment:")
        self.intro_comment_label.setProperty("styleClass", "heading")
        self.intro_comment_textedit = QTextEdit()
        self.comment_bank_label = QLabel("Comment Bank")
        self.comment_bank_label.setProperty("styleClass", "heading")
        self.comment_bank_listwidget = QListWidget()
        self.placeholder_instructions_label = QLabel(
            config.PLACEHOLDER_INSTRUCTIONS)
        self.add_comment_label = QLabel("Add Comment:")
        self.add_comment_entry = QLineEdit()
        self.add_comment_button = QPushButton("Add")
        self.update_comment_label = QLabel("Update Comment:")
        self.update_comment_entry = QLineEdit()
        self.update_comment_button = QPushButton("Update")
        self.delete_comment_button = QPushButton("Delete Comment")
        self.import_comments_combo = QComboBox()
        self.import_comments_button = QPushButton("Import...")
        self.cancel_button = QPushButton("Cancel")
        self.save_button = QPushButton("Save")

        # Layout
        self.layout = QVBoxLayout()
        self.top_layout = QHBoxLayout()
        self.intro_comment_layout = QVBoxLayout()
        self.intro_comment_layout.addWidget(self.intro_comment_label)
        self.intro_comment_layout.addWidget(self.intro_comment_textedit)
        self.top_layout.addLayout(self.intro_comment_layout)
        self.top_layout.addWidget(self.placeholder_instructions_label)
        self.layout.addLayout(self.top_layout)
        self.middle_layout = QVBoxLayout()
        self.middle_layout.addWidget(self.comment_bank_label)
        self.middle_layout.addWidget(self.comment_bank_listwidget)
        self.comment_actions_layout = QHBoxLayout()
        self.comment_actions_layout.addWidget(self.delete_comment_button, 0,
                                              Qt.AlignLeft)
        self.comment_actions_layout.addWidget(self.import_comments_combo, 1,
                                              Qt.AlignRight)
        self.comment_actions_layout.addWidget(self.import_comments_button, 0,
                                              Qt.AlignRight)
        self.middle_layout.addLayout(self.comment_actions_layout)
        self.update_comment_layout = QGridLayout()
        self.update_comment_layout.addWidget(self.update_comment_label, 0, 0)
        self.update_comment_layout.addWidget(self.update_comment_entry, 0, 1)
        self.update_comment_layout.addWidget(self.update_comment_button, 0, 2)
        self.update_comment_layout.addWidget(self.add_comment_label, 1, 0)
        self.update_comment_layout.addWidget(self.add_comment_entry, 1, 1)
        self.update_comment_layout.addWidget(self.add_comment_button, 1, 2)
        self.middle_layout.addLayout(self.update_comment_layout)
        self.layout.addLayout(self.middle_layout)
        self.bottom_layout = QHBoxLayout()
        self.bottom_layout.addWidget(self.cancel_button, 0, Qt.AlignLeft)
        self.bottom_layout.addWidget(self.save_button, 0, Qt.AlignRight)
        self.layout.addLayout(self.bottom_layout)

        # Slot connections
        self.comment_bank_listwidget.itemSelectionChanged.connect(
            self.do_update_comment_bank_selection)
        self.import_comments_button.clicked.connect(self.do_import_comments)
        self.update_comment_button.clicked.connect(self.do_update_comment)
        self.update_comment_entry.returnPressed.connect(self.do_update_comment)
        self.add_comment_button.clicked.connect(self.do_add_comment)
        self.add_comment_entry.returnPressed.connect(self.do_add_comment)
        self.delete_comment_button.clicked.connect(self.do_delete_comment)
        self.cancel_button.clicked.connect(self.do_cancel)
        self.save_button.clicked.connect(self.do_save)

        # Initial UI update
        self.update_ui()

        self.widget = QWidget()
        self.widget.setLayout(self.layout)
        self.setCentralWidget(self.widget)

    def update_ui(self):
        self.update_import_comments_list()
        self.update_intro_comment()
        self.update_comment_bank()

    def update_import_comments_list(self):
        self.import_comments_combo.clear()
        self.import_comments_combo.insertItems(0, self.saved_list)

    def update_intro_comment(self):
        self.intro_comment_textedit.clear()
        self.intro_comment_textedit.insertPlainText(
            self.subject['intro_comment'])

    def update_comment_bank(self):
        self.comment_bank_listwidget.clear()
        self.comment_bank_listwidget.addItems(self.subject['comment_bank'])
        self.do_update_comment_bank_selection()

    @Slot()
    def do_import_comments(self):
        # TODO confirm dialog first
        confirm_msg = QMessageBox(self)
        confirm_msg.setWindowTitle("Confirm")
        confirm_msg.setText("This will override current comments.")
        confirm_msg.setInformativeText("Do you want to continue?")
        confirm_msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        confirm_msg.setDefaultButton(QMessageBox.Yes)
        confirm = confirm_msg.exec()
        if confirm == QMessageBox.Yes:
            if self.import_comments_combo.count() > 0:
                new_subject = could_try_harder.load(
                    self.import_comments_combo.currentText())
                if new_subject:
                    self.subject['intro_comment'] = new_subject[
                        'intro_comment']
                    self.subject['comment_bank'] = new_subject['comment_bank']
                    self.update_ui()
                else:
                    # TODO better error handling here
                    print('Tried to import empty subject.')
                    return
        return

    @Slot()
    def do_update_comment_bank_selection(self):
        if self.comment_bank_listwidget.selectedItems():
            state = True
        else:
            state = False
        self.delete_comment_button.setEnabled(state)
        self.update_comment_button.setEnabled(state)
        # Update the text in the update comment line edit
        self.update_comment_entry.clear()
        if self.comment_bank_listwidget.currentItem():
            self.update_comment_entry.insert(
                self.comment_bank_listwidget.currentItem().text())

    @Slot()
    def do_update_comment(self):
        if self.update_comment_entry.text():
            self.comment_bank_listwidget.currentItem().setText(
                could_try_harder.do_style(
                    self.update_comment_entry.text().strip()))
            self.do_update_comment_bank_selection()

    @Slot()
    def do_add_comment(self):
        if self.add_comment_entry.text():
            self.comment_bank_listwidget.addItem(
                could_try_harder.do_style(
                    self.add_comment_entry.text().strip()))
            self.add_comment_entry.clear()
            self.do_update_comment_bank_selection()

    @Slot()
    def do_delete_comment(self):
        self.comment_bank_listwidget.takeItem(
            self.comment_bank_listwidget.currentRow())
        self.do_update_comment_bank_selection()

    @Slot()
    def do_cancel(self):
        self.close()

    @Slot()
    def do_save(self):
        self.subject['intro_comment'] = could_try_harder.do_style(
            self.intro_comment_textedit.toPlainText().strip())
        self.subject['comment_bank'] = []
        for i in range(self.comment_bank_listwidget.count()):
            self.subject['comment_bank'].append(
                self.comment_bank_listwidget.item(i).text())
        if could_try_harder.save(self.subject):
            self.close()
        else:
            # TODO better error handling here
            print("Save failed.")