Example #1
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 #2
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)