source: projects/punch-card/punch-card-editor/src/app/mainwindow.cc @ 52

Last change on this file since 52 was 52, checked in by sven, 10 years ago

Punch Card Editor: Code reordering and class renaming, rewriting.
Now using the namespace QPunchCard everywhere.

Parted the whole application into 5 parts/directories:

  • app: The application core with MainWindow and main() function
  • qpunchcard: Everything directly binary card related (no interpretation): modeling, input/output, view. Most important classes are Card, Deck, FileFormat, Widget
  • text: Everything related to text interpretation of Cards/Card Decks. Having the abstract Codec classes and the Text::Editor, Text::EditorDock
  • deckviewer: Application components like binary card editing central widget (CardEditor) and Navigator (Model View Controller classes)
  • driver: Basis for the driver framework, must be written soon.

Deck now hides the complete Storage to implement frontend methods that
implement versioning (Undo framework). All code was cleaned up, but doesn't
compile right now (still quite some non heavy errors).

-- Sven @ workstation

File size: 9.2 KB
Line 
1#include "mainwindow.h"
2#include "qpunchcard/card.h"
3#include "qpunchcard/widget.h"
4#include "deckviewer/navigatormodel.h"
5
6#include <QApplication>
7#include <QLabel>
8#include <QtDebug>
9#include <QListView>
10#include <QDockWidget>
11#include <QHBoxLayout>
12#include <QPushButton>
13#include <QMessageBox>
14#include <QFileDialog>
15#include <QFileInfo>
16
17using namespace QPunchCard;
18using namespace App;
19
20MainWindow::MainWindow() {
21        // sehr praktisch:
22        setAttribute(Qt::WA_DeleteOnClose, true);
23
24        // etwas kartenmaterial besorgen
25        Card foo;
26        foo.column[0] = 12;
27        foo.column[9] = 78;
28        foo.column[12][0] = true;
29        foo.column[12][9] = true;
30
31        deck = new Deck;
32        deck->push_back(foo);
33
34        for(int x = 0; x < 10; x++) {
35                Card c;
36                c.column[x] = x;
37                deck->push_back(c);
38        }
39
40        createGraphicalEditor();
41        createActions();
42        createMenus();
43        createToolBars();
44        createStatusBar();
45        createDockWindows();
46
47        // Titel einrichten und so
48        connect(this, SIGNAL(fileOpened(bool)), this, SLOT(window_update_on_file_state(bool)));
49        // und jetzt:
50
51        notifyFileOpened();
52}
53
54void MainWindow::createGraphicalEditor() {
55        graphical_editor = new CardEditor(this);
56        setCentralWidget(graphical_editor);
57        // signale und so:
58        connect(this, SIGNAL(cardSelected(DeckIndex)), graphical_editor, SLOT(setCard(DeckIndex)));
59        connect(this, SIGNAL(fileOpened(bool)), graphical_editor, SLOT(fileOpened(bool)));
60        connect(this, SIGNAL(contentsChanged(DeckIndex, DeckIndex)), graphical_editor, SLOT(contentsChanged(DeckIndex, DeckIndex)));
61
62}
63
64void MainWindow::window_update_on_file_state(bool opened) {
65        // * Window Title setzen
66        // * contentsChanged-Signal broadcasten
67        if(opened) {
68                // titel setzen
69                setWindowFilePath(QFileInfo(file).filePath());
70                setWindowTitle(tr("%1[*] - %2").arg(
71                        file.fileName().isEmpty() ? tr("New Card Deck") : file.fileName()
72                        ).arg(tr("Punch Card Editor")));
73                // Modified-Stern ([*]) verbinden
74                connect(deck, SIGNAL(modified(bool)), this, SLOT(setWindowModified(bool)));
75
76                // Broadcasting von "Edited" verbinden
77                connect(deck, SIGNAL(contentsChanged(DeckIndex, DeckIndex)), this, SIGNAL(contentsChanged(DeckIndex,DeckIndex)));
78        } else {
79                setWindowTitle(tr("Punch Card Editor"));
80                // passiert folgendes nicht sowieso automatisch?
81                disconnect(this, SLOT(setWindowModified(bool)));
82                // urhm, den broadcaster... nicht die slots freisetzen, waere bloed.
83        }
84}
85
86bool MainWindow::maybeSave() {
87        if(!deck->isModified())
88                return true;
89        if(deck->empty()) // oder sowas in der Art -- eine leere Lochkarte oder so
90                return true;
91        switch(QMessageBox::warning(this, tr("Punch Card Editor"),
92                tr("The document has been modified.\nDo you want to save your changes?"),
93                QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) {
94
95                case QMessageBox::Save:
96                        return saveFile();
97                case QMessageBox::Cancel:
98                        return false; // aborted the whole thing
99                default:
100                        return true; // discard the file
101        }
102}
103
104void MainWindow::newWindow() {
105        // einfacher gehts nicht:
106        new MainWindow();
107}
108
109void MainWindow::closeDeck() {
110        qDebug() << "Deleting deck.";
111        delete deck;
112        emit fileOpened(deck); // also false
113}
114
115void MainWindow::loadDeck(const QString& filename) {
116        // load a new deck from a file. There can still be an old deck open,
117        // this method will close it when everything went good
118        QFile file(filename);
119        const FileFormat* format = FileFormatFactory::createFormat(
120                                FileFormatFactory::autoDetectFormat(file)
121                             );
122        Deck* new_deck = new Deck(format);
123        // Leser anschmeissen
124        if( new_deck->read(file) ) {
125                statusBar()->showMessage(QString(tr("Deck read in successfully")), 4000);
126        } else
127                qDebug() << "Errors while reading in the Deck.";
128        // Alte Datei rausschmeissen
129        closeDeck();
130        // Neue setzen
131        deck = new_deck;
132        this->file.setFileName( file.fileName() );
133        notifyFileOpened();
134}
135
136void MainWindow::notifyFileOpened() {
137        if(deck) {
138                emit fileOpened(deck);
139                if(! deck->empty())
140                        emit setCard( deck->createIndex(0) );
141                else {
142                        // naja, das Deck ist *leer*. gibt also nix.
143                }
144        } else
145                qDebug("notifyFileOpened is supposed to be called when a file was *opened*");
146}
147
148void MainWindow::newFile() {
149        if(maybeSave()) {
150                // alte Datei schliessen.
151                // d.h. defakto: Deck loeschen, neues erstellen.
152                // und dann alle darueber informieren. Sehr kompliziert.
153                closeDeck();
154                deck = new Deck();
155                notifyFileOpened();
156        }
157}
158
159void MainWindow::openFile() {
160        if(maybeSave()) {
161                // Oeffnen-Dialog anzeigen.
162                QString filename = QFileDialog::getOpenFileName(this,
163                        tr("Open Card Deck File..."),
164                        QFileInfo(file).absolutePath(),
165                        tr("Jones Emulated Card Decks (*);;Card Editor XML-Files (*.xml *.cml)"));
166                if(!filename.isEmpty()) {
167                        loadDeck(filename);
168                }
169        }
170}
171
172bool MainWindow::saveFile() {
173        if(!file.exists() || !deck->canSave())
174                return saveFileAs();
175        else
176                return deck->save(file);
177}
178
179bool MainWindow::saveFileAs() {
180        // GUI anzeigen zum Speichern
181        QString filename = QFileDialog::getSaveFileName(this,
182                tr("Save Card Deck File..."),
183                QFileInfo(file).absolutePath(),
184                tr("Jones Emulator Card Decks (*);;Card Editor XML-Files (*.xml *.cml)"));
185        if(filename.isEmpty())
186                return false;
187        // Eigentlich jetzt: Nachschauen, welches Dateiformat zum Benutzen und so.
188        // stattdessen jetzt mal billig:
189        file.setFileName(filename);
190        if(deck->canSave()) {
191                // Nutze das bekannte Dateiformat
192                return deck->save(file);
193        } else {
194                // Nutze einfach mal
195                deck->setFormat( new JonesFileFormat );
196                if(deck->save(file)) {
197                        statusBar()->showMessage(QString(tr("Deck written successfully to %1").arg(filename)), 4000);
198                        return true;
199                } else {
200                        // todo: das hier als qmessagewindow oder so
201                        statusBar()->showMessage(QString(tr("Error while writing the deck")), 4000);
202                        return false;
203                }
204        }
205}
206
207void MainWindow::exportText() {
208        // Strategie: In die text_editors-Liste schauen, wenn nur ein Editor
209        // drin ist, ist der zu nutzende Codec klar definiert. Sonst fragen,
210        // welchen Codec benutzen.
211        // Dann abspeichern oder so... hier waere natuerlich auch interessant,
212        // auf bestehende Dateinamen zurueckgreifen zu koennen...
213}
214
215void MainWindow::exportPicture() {
216        // das haupteditorwidget bzw. nach Auswahl alle/bestimmte Karten als PNG/SVG/...
217        // rendern.
218}
219
220void MainWindow::closeFile() {
221        if(maybeSave()) {
222                // Deck schliessen und fertig.
223                closeDeck();
224        }
225}
226
227void MainWindow::quit() {
228        if(maybeSave()) {
229                // Deck schliesst automatisch ;-)
230                qApp->quit();
231        }
232}
233
234void MainWindow::closeEvent(QCloseEvent* event) {
235        if(maybeSave()) {
236                event->accept();
237        } else
238                event->ignore();
239}
240
241void MainWindow::help() {
242
243}
244
245void MainWindow::about() {
246        QMessageBox::about(this, tr("About the Punch Card Editor"),
247                tr("<big><b>Punch Card Editor</b></big><br>Development version"
248                   "<br>This application is GPLv3 licensed"
249                   "<br>Copyright Sven Koeppel"));
250}
251
252void MainWindow::newTextEditor() {
253        Text::EditorDock* editor = new Text::EditorDock(this);
254        addDockWidget(Qt::BottomDockWidgetArea, editor);
255        view_menu->addAction(editor->toggleViewAction());
256        text_editors.push_back(editor);
257
258        // Signale anschalten:
259        connect(editor, SIGNAL(cardSelected(DeckIndex)), this, SLOT(setCard(DeckIndex)));
260        connect(this, SIGNAL(cardSelected(DeckIndex)), editor, SLOT(setCard(DeckIndex)));
261        connect(this, SIGNAL(fileOpened(bool)), editor, SLOT(setVisible(bool)));
262        // TODO: klaeren, wer den Texteditor irgendwann mal killt
263        // -- ist diese Liste wirklich noetig? (ggf. *ja* wegen Textexport)
264}
265
266void MainWindow::nextCard() {
267        setCard( getCurrentIndex() + 1);
268}
269
270void MainWindow::prevCard() {
271        setCard( getCurrentIndex() - 1);
272}
273
274void MainWindow::setCard(DeckIndex i) {
275        // wenn keine Datei offen und so
276        if(!deck) {
277                qDebug("No card open, skipping setCard broadcasting");
278                return;
279        }
280        if(! i.assertDeck(deck)) {
281                qDebug() << "Index i has wrong deck: " << i;
282                return;
283        }
284        i.normalize();
285
286        // neuen index setzen
287        current_index = i;
288
289        // Signal weitergeben:
290        emit cardSelected(i);
291}
292
293void MainWindow::newCard() {
294        // append new Card behind current card
295        if(!deck) return;
296        if(deck->insert(current_index)) {
297                setCard( current_index+1 );
298        }
299
300        /*
301        int new_card_index = current_card + 1;
302        if(! deck->isValid(current_card))
303                new_card_index = 0; // insert card at beginning of deck
304        deck->insert( current_card + 1, new Card);
305        // ob das hier geht...
306        emit deck->contentsChanged(current_card, deck->count());
307        setCard( current_card + 1 );
308        */
309}
310
311void MainWindow::moveCardForwards() {
312        if(!deck) return;
313        if(deck->move(current_index, current_index+1)) {
314                setCard( current_index+1 );
315        }
316        /*
317        //DeckIndex new_index(deck, current_index + 1);
318        if(!deck->isValid(current_card) || !deck->isValid(new_card_index)) {
319                qDebug() << "Invalid indices for moveCardForwards";
320                return;
321        }
322        deck->move(current_card, new_card_index);
323        setCard( new_card_index );
324        */
325}
326
327void MainWindow::moveCardBackwards() {
328        if(!deck) return;
329        if(deck->move(current_index, current_index-1)) {
330                setCard( current_index-1 );
331        }
332        /*
333        int new_card_index = current_card - 1;
334        if(!deck->isValid(current_card) || !deck->isValid(new_card_index)) {
335                qDebug() << "Invalid indices for moveCardBackwards";
336                return;
337        }
338        deck->move(current_card, new_card_index);
339        setCard( new_card_index );
340        */
341}
342
343
344void MainWindow::createDockWindows() {
345        // Kartenuebersicht:
346        navigator = new Navigator::Dock(this);
347        addDockWidget(Qt::LeftDockWidgetArea, navigator);
348        view_menu->addAction(navigator->toggleViewAction());
349        // Signale werden natuerlich dort gemacht und so.
350}
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License