Example #1
0
    def set_information(self, desc=None):
        dialog = QDialog()
        dialog.setWindowTitle("Level Information")
        layout = QVBoxLayout()
        dialog.setLayout(layout)

        layout.addWidget(QLabel("Title:"))
        title_field = QLineEdit(self.scene.title or '')
        title_field.setMaxLength(50)
        layout.addWidget(title_field)

        layout.addWidget(QLabel("Author name:"))
        author_field = QLineEdit(self.scene.author or self.default_author
                                 or '')
        author_field.setMaxLength(20)
        layout.addWidget(author_field)
        old_author = author_field.text()

        information = (self.scene.information or '').splitlines()
        layout.addWidget(QLabel("Custom text hints:"))
        information1_field = QLineEdit(information[0] if information else '')
        information1_field.setMaxLength(120)
        layout.addWidget(information1_field)
        information2_field = QLineEdit(
            information[1] if len(information) > 1 else '')
        information2_field.setMaxLength(120)
        layout.addWidget(information2_field)

        layout.addWidget(
            QLabel("This text will be displayed within the level"))

        def accepted():
            self.scene.title = title_field.text().strip()
            self.scene.author = author_field.text().strip()
            if self.scene.author and self.scene.author != old_author:
                self.default_author = self.scene.author
            self.scene.information = '\n'.join(line for line in [
                information1_field.text().strip(),
                information2_field.text().strip()
            ] if line)
            self.changed()
            dialog.close()

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.rejected.connect(dialog.close)
        button_box.accepted.connect(accepted)
        layout.addWidget(button_box)

        dialog.exec_()
Example #2
0
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        self.network_access = QNetworkAccessManager()

        # TODO : a better regex that does not need <code></code> tags
        self.level_regex = re.compile('<code>(Hexcells level v1.*?)</code>',
                                      re.IGNORECASE | re.MULTILINE)

        self.setWindowTitle("Open from web page")
        self.setModal(True)
        layout = QVBoxLayout()
        self.setLayout(layout)

        url_selection = QHBoxLayout()
        url_selection.addWidget(QLabel("URL:"))
        self.url_field = QLineEdit(Dialog.current_url)
        self.url_field.setMinimumWidth(400)
        url_selection.addWidget(self.url_field)
        fetch_button = QPushButton("Fetch")
        fetch_button.clicked.connect(self.fetch_url)
        url_selection.addWidget(fetch_button)
        layout.addLayout(url_selection)

        self.fetch_in_progress = QProgressBar()
        layout.addWidget(self.fetch_in_progress)

        def level_selection_changed():
            self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)

        self.levels = QListWidget()
        layout.addWidget(self.levels)
        self.levels.itemSelectionChanged.connect(level_selection_changed)

        def rejected():
            self.selected_level_file = None
            self.reject()

        def accepted():
            self.selected_level_file = self.levels.selectedItems()[0].data(
                qt.UserRole)
            self.accept()

        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                           | QDialogButtonBox.Cancel)
        self.button_box.rejected.connect(rejected)
        self.button_box.accepted.connect(accepted)
        self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
        layout.addWidget(self.button_box)

        self.webpage_content = Dialog.current_content
        self.find_levels_in_content()
Example #3
0
    def __init__(self, playtest=False):
        QMainWindow.__init__(self)

        if not playtest:
            self.resize(1280, 720)
        self.setWindowIcon(QIcon(here('resources', 'player.ico')))

        self.scene = Scene()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        layout = QVBoxLayout()
        layout.setContentsMargins(QMargins())
        layout.setSpacing(0)
        self.central_widget.setLayout(layout)

        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)

        self.author_align_label = QLabel()
        self.author_align_label.setStyleSheet('color: rgba(0,0,0,0%)')
        top_layout.addWidget(self.author_align_label, 0)

        self.title_label = QLabel()
        self.title_label.setAlignment(qt.AlignHCenter)
        font = self.title_label.font()
        multiply_font_size(font, 1.8)
        self.title_label.setFont(font)
        top_layout.addWidget(self.title_label, 1)

        self.author_label = QLabel()
        self.author_label.setAlignment(qt.AlignRight)
        top_layout.addWidget(self.author_label, 0)

        self.view = View(self.scene)
        layout.addWidget(self.view, 1)

        self.information_label = QLabel()
        self.information_label.setAlignment(qt.AlignHCenter)
        self.information_label.setWordWrap(True)
        self.information_label.setContentsMargins(5, 5, 5, 5)
        font = self.information_label.font()
        multiply_font_size(font, 1.5)
        self.information_label.setFont(font)
        layout.addWidget(self.information_label)

        self.scene.playtest = self.playtest = playtest

        menu = self.menuBar().addMenu("&File")

        if not playtest:
            action = menu.addAction("&Open...", self.load_file,
                                    QKeySequence.Open)
            menu.addSeparator()
            action = menu.addAction("&Paste from Clipboard", self.paste,
                                    QKeySequence('Ctrl+V'))
            menu.addSeparator()

        action = menu.addAction(
            "&Quit", self.close,
            QKeySequence('Tab') if playtest else QKeySequence.Quit)
        if playtest:
            QShortcut(QKeySequence.Quit, self, action.trigger)
        else:
            QShortcut(QKeySequence.Close, self, action.trigger)

        menu = self.menuBar().addMenu("&Preferences")

        self.swap_buttons_action = action = make_check_action(
            "&Swap Buttons", self, self.scene, 'swap_buttons')
        menu.addAction(action)

        menu = self.menuBar().addMenu("&Solve")
        menu.setEnabled(solve is not None)

        menu.addAction("&One Step", self.scene.solve_step, QKeySequence("S"))

        menu.addAction("Confirm &Revealed", self.scene.confirm_proven,
                       QKeySequence("C"))

        menu.addAction("&Clear Revealed", self.scene.clear_proven,
                       QKeySequence("X"))

        menu.addSeparator()

        menu.addAction("&Solve Completely", self.scene.solve_complete,
                       QKeySequence("Shift+S"))

        menu = self.menuBar().addMenu("&Help")

        action = menu.addAction("&Instructions", help,
                                QKeySequence.HelpContents)

        action = menu.addAction("&About", lambda: about(self.title))

        self.last_used_folder = None

        self.reset()

        try:
            with open(here('player.cfg')) as cfg_file:
                cfg = cfg_file.read()
        except IOError:
            pass
        else:
            load_config(self, self.config_format, cfg)
Example #4
0
class MainWindow(QMainWindow):
    title = "SixCells Player"

    def __init__(self, playtest=False):
        QMainWindow.__init__(self)

        if not playtest:
            self.resize(1280, 720)
        self.setWindowIcon(QIcon(here('resources', 'player.ico')))

        self.scene = Scene()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        layout = QVBoxLayout()
        layout.setContentsMargins(QMargins())
        layout.setSpacing(0)
        self.central_widget.setLayout(layout)

        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)

        self.author_align_label = QLabel()
        self.author_align_label.setStyleSheet('color: rgba(0,0,0,0%)')
        top_layout.addWidget(self.author_align_label, 0)

        self.title_label = QLabel()
        self.title_label.setAlignment(qt.AlignHCenter)
        font = self.title_label.font()
        multiply_font_size(font, 1.8)
        self.title_label.setFont(font)
        top_layout.addWidget(self.title_label, 1)

        self.author_label = QLabel()
        self.author_label.setAlignment(qt.AlignRight)
        top_layout.addWidget(self.author_label, 0)

        self.view = View(self.scene)
        layout.addWidget(self.view, 1)

        self.information_label = QLabel()
        self.information_label.setAlignment(qt.AlignHCenter)
        self.information_label.setWordWrap(True)
        self.information_label.setContentsMargins(5, 5, 5, 5)
        font = self.information_label.font()
        multiply_font_size(font, 1.5)
        self.information_label.setFont(font)
        layout.addWidget(self.information_label)

        self.scene.playtest = self.playtest = playtest

        menu = self.menuBar().addMenu("&File")

        if not playtest:
            action = menu.addAction("&Open...", self.load_file,
                                    QKeySequence.Open)
            menu.addSeparator()
            action = menu.addAction("&Paste from Clipboard", self.paste,
                                    QKeySequence('Ctrl+V'))
            menu.addSeparator()

        action = menu.addAction(
            "&Quit", self.close,
            QKeySequence('Tab') if playtest else QKeySequence.Quit)
        if playtest:
            QShortcut(QKeySequence.Quit, self, action.trigger)
        else:
            QShortcut(QKeySequence.Close, self, action.trigger)

        menu = self.menuBar().addMenu("&Preferences")

        self.swap_buttons_action = action = make_check_action(
            "&Swap Buttons", self, self.scene, 'swap_buttons')
        menu.addAction(action)

        menu = self.menuBar().addMenu("&Solve")
        menu.setEnabled(solve is not None)

        menu.addAction("&One Step", self.scene.solve_step, QKeySequence("S"))

        menu.addAction("Confirm &Revealed", self.scene.confirm_proven,
                       QKeySequence("C"))

        menu.addAction("&Clear Revealed", self.scene.clear_proven,
                       QKeySequence("X"))

        menu.addSeparator()

        menu.addAction("&Solve Completely", self.scene.solve_complete,
                       QKeySequence("Shift+S"))

        menu = self.menuBar().addMenu("&Help")

        action = menu.addAction("&Instructions", help,
                                QKeySequence.HelpContents)

        action = menu.addAction("&About", lambda: about(self.title))

        self.last_used_folder = None

        self.reset()

        try:
            with open(here('player.cfg')) as cfg_file:
                cfg = cfg_file.read()
        except IOError:
            pass
        else:
            load_config(self, self.config_format, cfg)

    config_format = '''
        swap_buttons = swap_buttons_action.isChecked(); swap_buttons_action.setChecked(v)
        last_used_folder
        window_geometry_qt = save_geometry_qt(); restore_geometry_qt(v)
    '''

    def save_geometry_qt(self):
        return self.saveGeometry().toBase64().data().decode('ascii')

    def restore_geometry_qt(self, value):
        self.restoreGeometry(QByteArray.fromBase64(value.encode('ascii')))

    def reset(self):
        self.current_file = None
        self.scene.clear()
        self.scene.remaining = 0
        self.scene.mistakes = 0
        for it in [
                self.title_label, self.author_align_label, self.author_label,
                self.information_label
        ]:
            it.hide()
        try:
            del self.scene.all_cells
        except AttributeError:
            pass
        try:
            del self.scene.all_columns
        except AttributeError:
            pass

    @event_property
    def current_file(self):
        title = self.title
        if self.current_file:
            title = os.path.basename(self.current_file) + ' - ' + title
        self.setWindowTitle(("Playtest" + ' - ' if self.playtest else '') +
                            title)

    def load(self, struct):
        self.reset()
        load(struct, self.scene, Cell=Cell, Column=Column)
        self._prepare()

    def load_hexcells_file(self, file):
        import editor
        scene = editor.Scene()
        try:
            load_hexcells(file, scene, Cell=editor.Cell, Column=editor.Column)
        except ValueError as e:
            QMessageBox.critical(None, "Error", str(e))
            self.reset()
            return
        self.reset()
        self.load(save(scene)[0])
        self._prepare()
        if isinstance(file, basestring):
            self.current_file = file
            self.last_used_folder = os.path.dirname(file)
        return True

    def load_file(self, fn=None):
        if not fn:
            try:
                dialog = QFileDialog.getOpenFileNameAndFilter
            except AttributeError:
                dialog = QFileDialog.getOpenFileName
            fn, _ = dialog(
                self,
                "Open",
                filter=
                "Hexcells/SixCells Level (*.hexcells *sixcells *.sixcellz)")
        if not fn:
            return
        self.reset()
        if isinstance(fn, basestring) and fn.endswith('.hexcells'):
            self.load_hexcells_file(fn)
        else:
            gz = isinstance(fn, basestring) and fn.endswith('.sixcellz')
            if not load_file(fn, self.scene, gz=gz, Cell=Cell, Column=Column):
                self.reset()
                return
        self._prepare()
        if isinstance(fn, basestring):
            self.current_file = fn
            self.last_used_folder = os.path.dirname(fn)
        return True

    def _prepare(self):
        if not self.playtest:
            self.view.fit()
        remaining = 0
        for it in self.scene.all(Cell):
            if it.kind is not Cell.unknown:
                it.actual = it.kind
            if not it.revealed:
                if it.actual == Cell.full:
                    remaining += 1
                it.kind = Cell.unknown
        self.scene.remaining = remaining
        self.scene.mistakes = 0
        for txt, it in [
            (self.scene.title, self.title_label),
            (("by {}" if self.scene.author else "").format(self.scene.author),
             self.author_label),
            (("by {}" if self.scene.author else "").format(self.scene.author),
             self.author_align_label),
            (self.scene.information, self.information_label),
        ]:
            if txt:
                it.setText(txt)
                it.show()
            else:
                it.hide()

    def paste(self):
        text = app.clipboard().text()
        text = text.strip()
        if not text:
            return
        f = io.StringIO()
        f.write(text)
        f.seek(0)
        if not self.load_hexcells_file(f):
            self.reset()
            return
        self._prepare()

    def closeEvent(self, e):
        self.scene.solving = False

        cfg = save_config(self, self.config_format)
        with open(here('player.cfg'), 'w') as cfg_file:
            cfg_file.write(cfg)
Example #5
0
    def __init__(self, playtest=False):
        common.MainWindow.__init__(self)
        
        if not playtest:
            self.resize(1280, 720)
        self.setWindowIcon(QIcon(here('resources', 'player.ico')))

        self.scene = Scene()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        layout = QVBoxLayout()
        layout.setContentsMargins(QMargins())
        layout.setSpacing(0)
        self.central_widget.setLayout(layout)
        
        self.levels_bar = QTabBar()
        layout.addWidget(self.levels_bar)
        self.levels_bar.currentChanged.connect(self.level_change)
        
        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)
        
        self.author_align_label = QLabel()
        self.author_align_label.setStyleSheet('color: rgba(0,0,0,0%)')
        top_layout.addWidget(self.author_align_label, 0)
        
        self.title_label = QLabel()
        self.title_label.setAlignment(qt.AlignHCenter)
        update_font(self.title_label, lambda f: multiply_font_size(f, 1.8))
        top_layout.addWidget(self.title_label, 1)

        self.author_label = QLabel()
        self.author_label.setAlignment(qt.AlignRight)
        top_layout.addWidget(self.author_label, 0)
        
        
        self.view = View(self.scene)
        layout.addWidget(self.view, 1)

        self.information_label = QLabel()
        self.information_label.setAlignment(qt.AlignHCenter)
        self.information_label.setWordWrap(True)
        self.information_label.setContentsMargins(5, 5, 5, 5)
        update_font(self.information_label, lambda f: multiply_font_size(f, 1.5))
        layout.addWidget(self.information_label)

        self.scene.playtest = self.playtest = playtest
        
        
        menu = self.menuBar().addMenu("&File")
        
        if not playtest:
            action = menu.addAction("&Open...", self.load_file, QKeySequence.Open)
            menu.addSeparator()
        
        self.copy_action = action = menu.addAction("&Copy State to Clipboard", lambda: self.copy(display=True), QKeySequence('Ctrl+C'))
        action.setStatusTip("Copy the current state of the level into clipboard, in a text-based .hexcells format, padded with Tab characters.")
        if not playtest:
            action = menu.addAction("&Paste from Clipboard", self.paste, QKeySequence('Ctrl+V'))
            action.setStatusTip("Load a level in text-based .hexcells format that is currently in the clipboard.")
        menu.addSeparator()

        
        action = menu.addAction("&Quit", self.close, QKeySequence('Tab') if playtest else QKeySequence.Quit)
        if playtest:
            QShortcut(QKeySequence.Quit, self, action.trigger)
        
        
        menu = self.menuBar().addMenu("&Edit")
        
        action = menu.addAction("&Undo", self.scene.undo, QKeySequence.Undo)
        QShortcut(QKeySequence('Z'), self, action.trigger)
        action.setStatusTip("Cover the last uncovered cell.")
        action = menu.addAction("Clear &Progress", self.clear_progress)
        menu.addSeparator()
        
        menu.addAction("&Clear Annotations", self.scene.clear_guesses, QKeySequence("X"))
        menu.addAction("Con&firm Annotated Guesses", self.scene.confirm_guesses, QKeySequence("C"))
        menu.addAction("&Deny Annotated Guesses", self.scene.confirm_opposite_guesses, QKeySequence("D"))
        menu.addSeparator()
        
        menu.addAction("Highlight All C&olumn Hints", self.scene.highlight_all_columns)
        menu.addAction("Highlight All F&lower Hints", self.scene.highlight_all_flowers)

        
        menu = self.menuBar().addMenu("&Solve")
        menu.setEnabled(solve is not None)
        
        menu.addAction("&One Step", self.scene.solve_step, QKeySequence("S"))
        action = menu.addAction("Con&firm Solved", self.scene.confirm_guesses, QKeySequence("C"))
        action.setShortcutContext(qt.WidgetWithChildrenShortcut) # To prevent "ambiguous shortcut"
        action = menu.addAction("&Clear Solved", self.scene.clear_guesses, QKeySequence("X"))
        action.setShortcutContext(qt.WidgetWithChildrenShortcut)
        
        menu.addSeparator()
        
        menu.addAction("&Solve Completely", self.scene.solve_complete)

        
        menu = self.menuBar().addMenu("&Preferences")
        
        self.swap_buttons_action = action = make_check_action("&Swap Buttons", self, self.scene, 'swap_buttons')
        menu.addAction(action)

        
        menu = self.menuBar().addMenu("&Help")
        
        action = menu.addAction("&Instructions", self.help, QKeySequence.HelpContents)
        action = menu.addAction("&About", self.about)
        
        
        self.last_used_folder = None
        
        self.close_file()
        
        load_config_from_file(self, self.config_format, 'sixcells', 'player.cfg')
Example #6
0
class MainWindow(common.MainWindow):
    title = "SixCells Player"
    Cell = Cell
    Column = Column
    
    def __init__(self, playtest=False):
        common.MainWindow.__init__(self)
        
        if not playtest:
            self.resize(1280, 720)
        self.setWindowIcon(QIcon(here('resources', 'player.ico')))

        self.scene = Scene()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        layout = QVBoxLayout()
        layout.setContentsMargins(QMargins())
        layout.setSpacing(0)
        self.central_widget.setLayout(layout)
        
        self.levels_bar = QTabBar()
        layout.addWidget(self.levels_bar)
        self.levels_bar.currentChanged.connect(self.level_change)
        
        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)
        
        self.author_align_label = QLabel()
        self.author_align_label.setStyleSheet('color: rgba(0,0,0,0%)')
        top_layout.addWidget(self.author_align_label, 0)
        
        self.title_label = QLabel()
        self.title_label.setAlignment(qt.AlignHCenter)
        update_font(self.title_label, lambda f: multiply_font_size(f, 1.8))
        top_layout.addWidget(self.title_label, 1)

        self.author_label = QLabel()
        self.author_label.setAlignment(qt.AlignRight)
        top_layout.addWidget(self.author_label, 0)
        
        
        self.view = View(self.scene)
        layout.addWidget(self.view, 1)

        self.information_label = QLabel()
        self.information_label.setAlignment(qt.AlignHCenter)
        self.information_label.setWordWrap(True)
        self.information_label.setContentsMargins(5, 5, 5, 5)
        update_font(self.information_label, lambda f: multiply_font_size(f, 1.5))
        layout.addWidget(self.information_label)

        self.scene.playtest = self.playtest = playtest
        
        
        menu = self.menuBar().addMenu("&File")
        
        if not playtest:
            action = menu.addAction("&Open...", self.load_file, QKeySequence.Open)
            menu.addSeparator()
        
        self.copy_action = action = menu.addAction("&Copy State to Clipboard", lambda: self.copy(display=True), QKeySequence('Ctrl+C'))
        action.setStatusTip("Copy the current state of the level into clipboard, in a text-based .hexcells format, padded with Tab characters.")
        if not playtest:
            action = menu.addAction("&Paste from Clipboard", self.paste, QKeySequence('Ctrl+V'))
            action.setStatusTip("Load a level in text-based .hexcells format that is currently in the clipboard.")
        menu.addSeparator()

        
        action = menu.addAction("&Quit", self.close, QKeySequence('Tab') if playtest else QKeySequence.Quit)
        if playtest:
            QShortcut(QKeySequence.Quit, self, action.trigger)
        
        
        menu = self.menuBar().addMenu("&Edit")
        
        action = menu.addAction("&Undo", self.scene.undo, QKeySequence.Undo)
        QShortcut(QKeySequence('Z'), self, action.trigger)
        action.setStatusTip("Cover the last uncovered cell.")
        action = menu.addAction("Clear &Progress", self.clear_progress)
        menu.addSeparator()
        
        menu.addAction("&Clear Annotations", self.scene.clear_guesses, QKeySequence("X"))
        menu.addAction("Con&firm Annotated Guesses", self.scene.confirm_guesses, QKeySequence("C"))
        menu.addAction("&Deny Annotated Guesses", self.scene.confirm_opposite_guesses, QKeySequence("D"))
        menu.addSeparator()
        
        menu.addAction("Highlight All C&olumn Hints", self.scene.highlight_all_columns)
        menu.addAction("Highlight All F&lower Hints", self.scene.highlight_all_flowers)

        
        menu = self.menuBar().addMenu("&Solve")
        menu.setEnabled(solve is not None)
        
        menu.addAction("&One Step", self.scene.solve_step, QKeySequence("S"))
        action = menu.addAction("Con&firm Solved", self.scene.confirm_guesses, QKeySequence("C"))
        action.setShortcutContext(qt.WidgetWithChildrenShortcut) # To prevent "ambiguous shortcut"
        action = menu.addAction("&Clear Solved", self.scene.clear_guesses, QKeySequence("X"))
        action.setShortcutContext(qt.WidgetWithChildrenShortcut)
        
        menu.addSeparator()
        
        menu.addAction("&Solve Completely", self.scene.solve_complete)

        
        menu = self.menuBar().addMenu("&Preferences")
        
        self.swap_buttons_action = action = make_check_action("&Swap Buttons", self, self.scene, 'swap_buttons')
        menu.addAction(action)

        
        menu = self.menuBar().addMenu("&Help")
        
        action = menu.addAction("&Instructions", self.help, QKeySequence.HelpContents)
        action = menu.addAction("&About", self.about)
        
        
        self.last_used_folder = None
        
        self.close_file()
        
        load_config_from_file(self, self.config_format, 'sixcells', 'player.cfg')

    
    config_format = '''
        swap_buttons = swap_buttons_action.isChecked(); swap_buttons_action.setChecked(v)
        antialiasing = view.antialiasing; view.antialiasing = v
        last_used_folder
        window_geometry_qt = save_geometry_qt(); restore_geometry_qt(v)
    '''
    
    def close_file(self):
        if not self.playtest:
            total = 0
            revealed = 0
            for cell in self.scene.all(Cell):
                if not cell.revealed:
                    total += 1
                    if cell.display is not Cell.unknown:
                        revealed += 1
            clearing = hasattr(self, 'clearing')
            if 0 < revealed < total or clearing:
                try:
                    saved = save(self.scene, display=True, padding=False)
                    do_save = self.original_level != saved
                    if do_save:
                        if not clearing:
                            msg = "Would you like to save your progress for this level?"
                            btn = QMessageBox.warning(self, "Unsaved progress", msg, QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Save)
                        else:
                            msg = "Are you sure you want to clear progress for this level?"
                            btn = QMessageBox.warning(self, "Clear progress", msg, QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Discard)
                        if btn == QMessageBox.Discard:
                            do_save = False
                        elif btn == QMessageBox.Cancel:
                            return
                    with db_connection('sixcells.sqlite3') as con:
                        with con:
                            con.execute('CREATE TABLE IF NOT EXISTS `saves` (`level` TEXT PRIMARY KEY, `save` TEXT, `mistakes` INT)')
                            con.execute('DELETE FROM `saves` WHERE `level` = ?', (self.original_level,))
                            if do_save:
                                con.execute('INSERT INTO `saves` (`level`, `save`, `mistakes`) VALUES (?, ?, ?)', (self.original_level, saved, self.scene.mistakes))
                except Exception as e:
                    pass
        self.current_file = None
        self.scene.clear()
        self.scene.remaining = 0
        self.scene.mistakes = 0
        self.scene.reset_cache()
        for it in [self.title_label, self.author_align_label, self.author_label, self.information_label]:
            it.hide()
        self.copy_action.setEnabled(False)
        self.undo_history = []
        self.view.progress_loaded_timer.stop()
        self.view.viewport().repaint()
        return True
    
    def clear_progress(self):
        self.clearing = True
        self.load_one(self.original_level)
        delattr(self, 'clearing')
    
    @event_property
    def current_file(self):
        title = self.title
        if self.current_file:
            title = os.path.basename(self.current_file) + ' - ' + title
        self.setWindowTitle(("Playtest" + ' - ' if self.playtest else '') + title)
    
    def prepare(self):
        if not self.playtest:
            self.view.fit()
        remaining = 0
        for i, cell in enumerate(self.scene.all(Cell)):
            cell.id = i
            if cell.kind is Cell.full and not cell.revealed:
                remaining += 1
            cell._display = cell.kind if cell.revealed else Cell.unknown
        for i, col in enumerate(self.scene.all(Column)):
            col.id = i
        self.scene.remaining = remaining
        self.scene.mistakes = 0
        author_text = ("by {}" if self.scene.author else "").format(self.scene.author)
        for txt, it in [
            (self.scene.title, self.title_label),
            (author_text, self.author_label),
            (author_text, self.author_align_label),
            (self.scene.information, self.information_label),
        ]:
            if txt:
                it.setText(txt)
                it.show()
            else:
                it.hide()
        self.scene.full_upd()
        self.copy_action.setEnabled(True)
    
    def load_one(self, level):
        if common.MainWindow.load(self, level):
            self.original_level = save(self.scene, padding=False)
            try:
                with db_connection('sixcells.sqlite3') as con:
                    with con:
                        [(saved, mistakes)] = con.execute('SELECT `save`, `mistakes` FROM `saves` WHERE `level` = ?', (self.original_level,))
                common.MainWindow.load(self, saved)
                self.scene.mistakes = mistakes
                self.view.progress_loaded_timer.start()
                self.view.viewport().update()
            except Exception:
                pass
            self.view.setFocus()
            return True
    
    def load(self, level):
        while self.levels_bar.count():
            self.levels_bar.removeTab(0)
        self.levels_bar.hide()
        levels = []
        lines = level.splitlines()
        start = None
        skip = 0
        for i, line in enumerate(lines + [None]):
            if skip:
                skip -= 1
                continue
            if line is None or line.strip() == 'Hexcells level v1':
                if start is not None:
                    level_lines = lines[start:i]
                    levels.append(('\n'.join(level_lines), level_lines[1]))
                start = i
                skip = 4
        self.current_level = 0
        if len(levels) > 1:
            self.levels_bar.show()
            self.load_one(levels[0][0])
            for level, title in levels:
                self.levels_bar.addTab(title)
                self.levels_bar.setTabData(self.levels_bar.count()-1, level)
        else:
            self.load_one(level)

    def level_change(self, index):
        if index >= 0 and index != self.current_level:
            level = self.levels_bar.tabData(index)
            if level:
                if self.load_one(level):
                    self.current_level = index
                else:
                    self.levels_bar.setCurrentIndex(self.current_level)


    def closeEvent(self, e):
        if not self.close_file():
            e.ignore()
            return
        self.scene.solving = 0

        save_config_to_file(self, self.config_format, 'sixcells', 'player.cfg')
Example #7
0
    def __init__(self, playtest=False):
        QMainWindow.__init__(self)
        
        if not playtest:
            self.resize(1280, 720)
        self.setWindowIcon(QIcon(here('resources', 'player.ico')))

        self.scene = Scene()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        layout = QVBoxLayout()
        layout.setContentsMargins(QMargins())
        layout.setSpacing(0)
        self.central_widget.setLayout(layout)
        
        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)
        
        self.author_align_label = QLabel()
        self.author_align_label.setStyleSheet('color: rgba(0,0,0,0%)')
        top_layout.addWidget(self.author_align_label, 0)
        
        self.title_label = QLabel()
        self.title_label.setAlignment(qt.AlignHCenter)
        font = self.title_label.font()
        multiply_font_size(font, 1.8)
        self.title_label.setFont(font)
        top_layout.addWidget(self.title_label, 1)

        self.author_label = QLabel()
        self.author_label.setAlignment(qt.AlignRight)
        top_layout.addWidget(self.author_label, 0)
        
        
        self.view = View(self.scene)
        layout.addWidget(self.view, 1)

        self.information_label = QLabel()
        self.information_label.setAlignment(qt.AlignHCenter)
        self.information_label.setWordWrap(True)
        self.information_label.setContentsMargins(5, 5, 5, 5)
        font = self.information_label.font()
        multiply_font_size(font, 1.5)
        self.information_label.setFont(font)
        layout.addWidget(self.information_label)

        self.scene.playtest = self.playtest = playtest
        
        
        menu = self.menuBar().addMenu("&File")
        
        if not playtest:
            action = menu.addAction("&Open...", self.load_file, QKeySequence.Open)
            menu.addSeparator()
            action = menu.addAction("&Paste from Clipboard", self.paste, QKeySequence('Ctrl+V'))
            menu.addSeparator()

        
        action = menu.addAction("&Quit", self.close, QKeySequence('Tab') if playtest else QKeySequence.Quit)
        if playtest:
            QShortcut(QKeySequence.Quit, self, action.trigger)
        else:
            QShortcut(QKeySequence.Close, self, action.trigger)
        
        
        menu = self.menuBar().addMenu("&Preferences")
        
        self.swap_buttons_action = action = make_check_action("&Swap Buttons", self, self.scene, 'swap_buttons')
        menu.addAction(action)

        
        menu = self.menuBar().addMenu("&Solve")
        menu.setEnabled(solve is not None)
        
        menu.addAction("&One Step", self.scene.solve_step, QKeySequence("S"))
        
        menu.addAction("Confirm &Revealed", self.scene.confirm_proven, QKeySequence("C"))
        
        menu.addAction("&Clear Revealed", self.scene.clear_proven, QKeySequence("X"))
        
        menu.addSeparator()
        
        menu.addAction("&Solve Completely", self.scene.solve_complete, QKeySequence("Shift+S"))

        
        menu = self.menuBar().addMenu("&Help")
        
        action = menu.addAction("&Instructions", help, QKeySequence.HelpContents)
        
        action = menu.addAction("&About", lambda: about(self.title))
        
        
        self.last_used_folder = None
        
        self.reset()
        
        try:
            with open(here('player.cfg')) as cfg_file:
                cfg = cfg_file.read()
        except IOError:
            pass
        else:
            load_config(self, self.config_format, cfg)
Example #8
0
class MainWindow(QMainWindow):
    title = "SixCells Player"
    
    def __init__(self, playtest=False):
        QMainWindow.__init__(self)
        
        if not playtest:
            self.resize(1280, 720)
        self.setWindowIcon(QIcon(here('resources', 'player.ico')))

        self.scene = Scene()

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        layout = QVBoxLayout()
        layout.setContentsMargins(QMargins())
        layout.setSpacing(0)
        self.central_widget.setLayout(layout)
        
        top_layout = QHBoxLayout()
        layout.addLayout(top_layout)
        
        self.author_align_label = QLabel()
        self.author_align_label.setStyleSheet('color: rgba(0,0,0,0%)')
        top_layout.addWidget(self.author_align_label, 0)
        
        self.title_label = QLabel()
        self.title_label.setAlignment(qt.AlignHCenter)
        font = self.title_label.font()
        multiply_font_size(font, 1.8)
        self.title_label.setFont(font)
        top_layout.addWidget(self.title_label, 1)

        self.author_label = QLabel()
        self.author_label.setAlignment(qt.AlignRight)
        top_layout.addWidget(self.author_label, 0)
        
        
        self.view = View(self.scene)
        layout.addWidget(self.view, 1)

        self.information_label = QLabel()
        self.information_label.setAlignment(qt.AlignHCenter)
        self.information_label.setWordWrap(True)
        self.information_label.setContentsMargins(5, 5, 5, 5)
        font = self.information_label.font()
        multiply_font_size(font, 1.5)
        self.information_label.setFont(font)
        layout.addWidget(self.information_label)

        self.scene.playtest = self.playtest = playtest
        
        
        menu = self.menuBar().addMenu("&File")
        
        if not playtest:
            action = menu.addAction("&Open...", self.load_file, QKeySequence.Open)
            menu.addSeparator()
            action = menu.addAction("&Paste from Clipboard", self.paste, QKeySequence('Ctrl+V'))
            menu.addSeparator()

        
        action = menu.addAction("&Quit", self.close, QKeySequence('Tab') if playtest else QKeySequence.Quit)
        if playtest:
            QShortcut(QKeySequence.Quit, self, action.trigger)
        else:
            QShortcut(QKeySequence.Close, self, action.trigger)
        
        
        menu = self.menuBar().addMenu("&Preferences")
        
        self.swap_buttons_action = action = make_check_action("&Swap Buttons", self, self.scene, 'swap_buttons')
        menu.addAction(action)

        
        menu = self.menuBar().addMenu("&Solve")
        menu.setEnabled(solve is not None)
        
        menu.addAction("&One Step", self.scene.solve_step, QKeySequence("S"))
        
        menu.addAction("Confirm &Revealed", self.scene.confirm_proven, QKeySequence("C"))
        
        menu.addAction("&Clear Revealed", self.scene.clear_proven, QKeySequence("X"))
        
        menu.addSeparator()
        
        menu.addAction("&Solve Completely", self.scene.solve_complete, QKeySequence("Shift+S"))

        
        menu = self.menuBar().addMenu("&Help")
        
        action = menu.addAction("&Instructions", help, QKeySequence.HelpContents)
        
        action = menu.addAction("&About", lambda: about(self.title))
        
        
        self.last_used_folder = None
        
        self.reset()
        
        try:
            with open(here('player.cfg')) as cfg_file:
                cfg = cfg_file.read()
        except IOError:
            pass
        else:
            load_config(self, self.config_format, cfg)
    
    config_format = '''
        swap_buttons = swap_buttons_action.isChecked(); swap_buttons_action.setChecked(v)
        last_used_folder
        window_geometry_qt = save_geometry_qt(); restore_geometry_qt(v)
    '''
    def save_geometry_qt(self):
        return self.saveGeometry().toBase64().data().decode('ascii')
    def restore_geometry_qt(self, value):
        self.restoreGeometry(QByteArray.fromBase64(value.encode('ascii')))
    
    def reset(self):
        self.current_file = None
        self.scene.clear()
        self.scene.remaining = 0
        self.scene.mistakes = 0
        for it in [self.title_label, self.author_align_label, self.author_label, self.information_label]:
            it.hide()
        try:
            del self.scene.all_cells
        except AttributeError: pass
        try:
            del self.scene.all_columns
        except AttributeError: pass
    
    @event_property
    def current_file(self):
        title = self.title
        if self.current_file:
            title = os.path.basename(self.current_file)+' - '+title
        self.setWindowTitle(("Playtest"+' - ' if self.playtest else '')+title)
    
    def load(self, struct):
        self.reset()
        load(struct, self.scene, Cell=Cell, Column=Column)
        self._prepare()
    
    def load_hexcells_file(self, file):
        import editor
        scene = editor.Scene()
        try:
            load_hexcells(file, scene, Cell=editor.Cell, Column=editor.Column)
        except ValueError as e:
            QMessageBox.critical(None, "Error", str(e))
            self.reset()
            return
        self.reset()
        self.load(save(scene)[0])
        self._prepare()
        if isinstance(file, basestring):
            self.current_file = file
            self.last_used_folder = os.path.dirname(file)
        return True
    
    def load_file(self, fn=None):
        if not fn:
            try:
                dialog = QFileDialog.getOpenFileNameAndFilter
            except AttributeError:
                dialog = QFileDialog.getOpenFileName
            fn, _ = dialog(self, "Open", filter="Hexcells/SixCells Level (*.hexcells *sixcells *.sixcellz)")
        if not fn:
            return
        self.reset()
        if isinstance(fn, basestring) and fn.endswith('.hexcells'):
            self.load_hexcells_file(fn)
        else:
            gz = isinstance(fn, basestring) and fn.endswith('.sixcellz')
            if not load_file(fn, self.scene, gz=gz, Cell=Cell, Column=Column):
                self.reset()
                return
        self._prepare()
        if isinstance(fn, basestring):
            self.current_file = fn
            self.last_used_folder = os.path.dirname(fn)
        return True
    
    def _prepare(self):
        if not self.playtest:
            self.view.fit()
        remaining = 0
        for it in self.scene.all(Cell):
            if it.kind is not Cell.unknown:
                it.actual = it.kind
            if not it.revealed:
                if it.actual == Cell.full:
                    remaining += 1
                it.kind = Cell.unknown
        self.scene.remaining = remaining
        self.scene.mistakes = 0
        for txt, it in [
            (self.scene.title, self.title_label),
            (("by {}" if self.scene.author else "").format(self.scene.author), self.author_label),
            (("by {}" if self.scene.author else "").format(self.scene.author), self.author_align_label),
            (self.scene.information, self.information_label),
        ]:
            if txt:
                it.setText(txt)
                it.show()
            else:
                it.hide()

    def paste(self):
        text = app.clipboard().text()
        text = text.strip()
        if not text:
            return
        f = io.StringIO()
        f.write(text)
        f.seek(0)
        if not self.load_hexcells_file(f):
            self.reset()
            return
        self._prepare()


    def closeEvent(self, e):
        self.scene.solving = False

        cfg = save_config(self, self.config_format)
        with open(here('player.cfg'), 'w') as cfg_file:
            cfg_file.write(cfg)