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

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

Punch Card Editor, ongoing development

  • Extended new Deck interface, expanding the undo framework
  • Implemented editor changes via undo framework
  • revised the menu and toolbar actions and structure (now dynamic construction at deck load time), implemented undo viewer
  • Started implementation of device driver framework in menu
  • Embedded the Qextserialport library (http://qextserialport.sourceforge.net/)
  • Started the Documation M200 Client device driver (well, just created the directory structure and qmake project file infrastructure)
  • At the current state, the complete project compiles :-)

Statistics: About 3500 Lines of code (without libqextserialport)

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