Mercurial > projects > qtd
annotate examples/mainwindows/sdi/mainwindow.d @ 282:256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
author | eldar |
---|---|
date | Fri, 16 Oct 2009 02:43:59 +0000 |
parents | 5df570e79cfc |
children | 7a3c43424dca |
rev | line source |
---|---|
269 | 1 /**************************************************************************** |
2 ** | |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). | |
4 ** Contact: Nokia Corporation (qt-info@nokia.com) | |
5 ** | |
6 ** This file is part of the examples of the Qt Toolkit. | |
7 ** | |
8 ** $QT_BEGIN_LICENSE:LGPL$ | |
9 ** Commercial Usage | |
10 ** Licensees holding valid Qt Commercial licenses may use this file in | |
11 ** accordance with the Qt Commercial License Agreement provided with the | |
12 ** Software or, alternatively, in accordance with the terms contained in | |
13 ** a written agreement between you and Nokia. | |
14 ** | |
15 ** GNU Lesser General Public License Usage | |
16 ** Alternatively, this file may be used under the terms of the GNU Lesser | |
17 ** General Public License version 2.1 as published by the Free Software | |
18 ** Foundation and appearing in the file LICENSE.LGPL included in the | |
19 ** packaging of this file. Please review the following information to | |
20 ** ensure the GNU Lesser General Public License version 2.1 requirements | |
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
22 ** | |
23 ** In addition, as a special exception, Nokia gives you certain | |
24 ** additional rights. These rights are described in the Nokia Qt LGPL | |
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this | |
26 ** package. | |
27 ** | |
28 ** GNU General Public License Usage | |
29 ** Alternatively, this file may be used under the terms of the GNU | |
30 ** General Public License version 3.0 as published by the Free Software | |
31 ** Foundation and appearing in the file LICENSE.GPL included in the | |
32 ** packaging of this file. Please review the following information to | |
33 ** ensure the GNU General Public License version 3.0 requirements will be | |
34 ** met: http://www.gnu.org/copyleft/gpl.html. | |
35 ** | |
36 ** If you are unsure which license is appropriate for your use, please | |
37 ** contact the sales department at http://www.qtsoftware.com/contact. | |
38 ** $QT_END_LICENSE$ | |
39 ** | |
40 ****************************************************************************/ | |
41 | |
42 /**************************************************************************** | |
43 ** | |
44 ** Translated from Qt/C++ to QtD/D by Jason Addison | |
45 ** Date: 2009 09 13 | |
46 ** Contact: jraddison@gmail.com | |
47 ** | |
48 ****************************************************************************/ | |
49 | |
50 | |
51 import qt.gui.QMainWindow; | |
52 import qt.gui.QAction; | |
53 import qt.gui.QMenu; | |
54 import qt.gui.QTextEdit; | |
55 import qt.gui.QFileDialog; | |
56 import qt.gui.QMessageBox; | |
57 import qt.core.QSettings; | |
58 import qt.core.QTextStream; | |
59 | |
60 version(Tango) | |
61 { | |
62 import tango.text.Util; | |
63 import Int = tango.text.convert.Integer; | |
64 } | |
65 else | |
66 { | |
67 import std.string; | |
68 import std.conv; | |
69 } | |
70 class MainWindow : public QMainWindow | |
71 { | |
72 // Q_OBJECT | |
73 | |
74 public: | |
75 this() | |
76 { | |
77 init(); | |
78 setCurrentFile(""); | |
79 } | |
80 | |
81 this(string fileName) | |
82 { | |
83 init(); | |
84 loadFile(fileName); | |
85 } | |
86 | |
87 protected: | |
88 | |
89 void closeEvent(QCloseEvent event) | |
90 { | |
91 if (maybeSave()) { | |
92 writeSettings(); | |
93 event.accept(); | |
94 } else { | |
95 event.ignore(); | |
96 } | |
97 } | |
98 | |
99 private: // slots | |
100 | |
101 void newFile() | |
102 { | |
103 MainWindow other = new MainWindow; | |
104 other.move(x() + 40, y() + 40); | |
105 other.show(); | |
106 } | |
107 | |
108 void open() | |
109 { | |
110 scope fileName = QFileDialog.getOpenFileName(this); | |
111 if (fileName) { | |
112 MainWindow existing = findMainWindow(fileName); | |
113 if (existing) { | |
114 existing.show(); | |
115 existing.raise(); | |
116 existing.activateWindow(); | |
117 return; | |
118 } | |
119 if (isUntitled && textEdit.document().isEmpty() | |
120 && !isWindowModified()) { | |
121 loadFile(fileName); | |
122 } else { | |
123 MainWindow other = new MainWindow(fileName); | |
124 if (other.isUntitled) { | |
125 delete other; | |
126 return; | |
127 } | |
128 other.move(x() + 40, y() + 40); | |
129 other.show(); | |
130 } | |
131 } | |
132 } | |
133 | |
134 bool save() | |
135 { | |
136 if (isUntitled) { | |
137 return saveAs(); | |
138 } else { | |
139 return saveFile(curFile); | |
140 } | |
141 } | |
142 | |
143 bool saveAs() | |
144 { | |
145 string fileName = QFileDialog.getSaveFileName(this, tr("Save As"), | |
146 curFile); | |
147 if (!fileName) | |
148 return false; | |
149 | |
150 return saveFile(fileName); | |
151 } | |
152 | |
153 void about() | |
154 { | |
155 QMessageBox.about(this, tr("About SDI"), | |
156 tr("The <b>SDI</b> example demonstrates how to write single " ~ | |
157 "document interface applications using Qt.")); | |
158 } | |
159 | |
160 void documentWasModified() | |
161 { | |
162 setWindowModified(true); | |
163 } | |
164 | |
165 private: | |
166 | |
167 void init() | |
168 { | |
169 setAttribute(Qt.WA_DeleteOnClose); | |
170 | |
171 isUntitled = true; | |
172 | |
173 textEdit = new QTextEdit; | |
174 setCentralWidget(textEdit); | |
175 | |
176 createActions(); | |
177 createMenus(); | |
178 createToolBars(); | |
179 createStatusBar(); | |
180 | |
181 readSettings(); | |
182 | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
183 connect!("contentsChanged")(textEdit.document(), &this.documentWasModified); |
269 | 184 |
185 setUnifiedTitleAndToolBarOnMac(true); | |
186 } | |
187 | |
188 void createActions() | |
189 { | |
190 newAct = new QAction(new QIcon(":/images/new.png"), tr("&New"), this); | |
191 newAct.setShortcuts(QKeySequence.New); | |
192 newAct.setStatusTip(tr("Create a new file")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
193 connect!("triggered")(newAct, &this.newFile); |
269 | 194 |
195 openAct = new QAction(new QIcon(":/images/open.png"), tr("&Open..."), this); | |
196 openAct.setShortcuts(QKeySequence.Open); | |
197 openAct.setStatusTip(tr("Open an existing file")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
198 connect!("triggered")(openAct, &this.open); |
269 | 199 |
200 saveAct = new QAction(new QIcon(":/images/save.png"), tr("&Save"), this); | |
201 saveAct.setShortcuts(QKeySequence.Save); | |
202 saveAct.setStatusTip(tr("Save the document to disk")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
203 connect!("triggered")(saveAct, &this.save); |
269 | 204 |
205 saveAsAct = new QAction(tr("Save &As..."), this); | |
206 saveAsAct.setShortcuts(QKeySequence.SaveAs); | |
207 saveAsAct.setStatusTip(tr("Save the document under a new name")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
208 connect!("triggered")(saveAsAct, &this.saveAs); |
269 | 209 |
210 closeAct = new QAction(tr("&Close"), this); | |
211 closeAct.setShortcut(tr("Ctrl+W")); | |
212 closeAct.setStatusTip(tr("Close this window")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
213 connect!("triggered")(closeAct, &this.close); |
269 | 214 |
215 exitAct = new QAction(tr("E&xit"), this); | |
216 exitAct.setShortcut(tr("Ctrl+Q")); | |
217 exitAct.setStatusTip(tr("Exit the application")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
218 connect!("triggered")(exitAct, &QApplication.closeAllWindows); |
269 | 219 |
220 cutAct = new QAction(new QIcon(":/images/cut.png"), tr("Cu&t"), this); | |
221 cutAct.setShortcuts(QKeySequence.Cut); | |
222 cutAct.setStatusTip(tr("Cut the current selection's contents to the " ~ | |
223 "clipboard")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
224 connect!("triggered")(cutAct, &textEdit.cut); |
269 | 225 |
226 copyAct = new QAction(new QIcon(":/images/copy.png"), tr("&Copy"), this); | |
227 copyAct.setShortcuts(QKeySequence.Copy); | |
228 copyAct.setStatusTip(tr("Copy the current selection's contents to the " ~ | |
229 "clipboard")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
230 connect!("triggered")(copyAct, &textEdit.copy); |
269 | 231 |
232 pasteAct = new QAction(new QIcon(":/images/paste.png"), tr("&Paste"), this); | |
233 pasteAct.setShortcuts(QKeySequence.Paste); | |
234 pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " ~ | |
235 "selection")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
236 connect!("triggered")(pasteAct, &textEdit.paste); |
269 | 237 |
238 aboutAct = new QAction(tr("&About"), this); | |
239 aboutAct.setStatusTip(tr("Show the application's About box")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
240 connect!("triggered")(aboutAct, &this.about); |
269 | 241 |
242 aboutQtAct = new QAction(tr("About &Qt"), this); | |
243 aboutQtAct.setStatusTip(tr("Show the Qt library's About box")); | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
244 connect!("triggered")(aboutQtAct, &QApplication.aboutQt); |
269 | 245 |
246 cutAct.setEnabled(false); | |
247 copyAct.setEnabled(false); | |
248 | |
282
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
249 connect!("copyAvailable")(textEdit, &cutAct.setEnabled); |
256ab6cb8e85
Signals look-up andNew syntax for connect. The old one will not work from now on. This will allow for the signals overload. Although changes are done for both D1 and D2 versions, D1 won't work because of compiler bugs. I am tired of waiting for fixes.
eldar
parents:
278
diff
changeset
|
250 connect!("copyAvailable")(textEdit, ©Act.setEnabled); |
269 | 251 } |
252 | |
253 void createMenus() | |
254 { | |
255 fileMenu = menuBar.addMenu(tr("&File")); | |
256 fileMenu.addAction(newAct); | |
257 fileMenu.addAction(openAct); | |
258 fileMenu.addAction(saveAct); | |
259 fileMenu.addAction(saveAsAct); | |
260 fileMenu.addSeparator(); | |
261 fileMenu.addAction(closeAct); | |
262 fileMenu.addAction(exitAct); | |
263 | |
264 editMenu = menuBar.addMenu(tr("&Edit")); | |
265 editMenu.addAction(cutAct); | |
266 editMenu.addAction(copyAct); | |
267 editMenu.addAction(pasteAct); | |
268 | |
269 menuBar().addSeparator(); | |
270 | |
271 helpMenu = menuBar.addMenu(tr("&Help")); | |
272 helpMenu.addAction(aboutAct); | |
273 helpMenu.addAction(aboutQtAct); | |
274 } | |
275 | |
276 void createToolBars() | |
277 { | |
278 fileToolBar = addToolBar(tr("File")); | |
279 fileToolBar.addAction(newAct); | |
280 fileToolBar.addAction(openAct); | |
281 fileToolBar.addAction(saveAct); | |
282 | |
283 editToolBar = addToolBar(tr("Edit")); | |
284 editToolBar.addAction(cutAct); | |
285 editToolBar.addAction(copyAct); | |
286 editToolBar.addAction(pasteAct); | |
287 } | |
288 | |
289 void createStatusBar() | |
290 { | |
291 statusBar.showMessage(tr("Ready")); | |
292 } | |
293 | |
294 void readSettings() | |
295 { | |
296 scope QSettings settings = new QSettings("Trolltech", "SDI Example"); | |
297 scope QPoint pos = settings.value("pos", new QVariant(QPoint(200, 200))).toPoint(); | |
298 scope QSize size = settings.value("size", new QVariant(QSize(400, 400))).toSize(); | |
299 move(pos); | |
300 resize(size); | |
301 } | |
302 | |
303 void writeSettings() | |
304 { | |
305 QSettings settings = new QSettings("Trolltech", "SDI Example"); | |
306 settings.setValue("pos", new QVariant(pos())); | |
307 settings.setValue("size", new QVariant(size())); | |
308 } | |
309 | |
310 bool maybeSave() | |
311 { | |
312 if (textEdit.document().isModified()) { | |
313 QMessageBox.StandardButton ret; | |
314 ret = QMessageBox.warning(this, tr("SDI"), | |
315 tr("The document has been modified.\n" ~ | |
316 "Do you want to save your changes?"), | |
317 QMessageBox.Save | QMessageBox.Discard | |
318 | QMessageBox.Cancel); | |
319 if (ret == QMessageBox.Save) | |
320 return save(); | |
321 else if (ret == QMessageBox.Cancel) | |
322 return false; | |
323 } | |
324 return true; | |
325 } | |
326 | |
327 void loadFile(string fileName) | |
328 { | |
329 scope file = new QFile(fileName); | |
330 if (!file.open(QFile.ReadOnly | QFile.Text)) { | |
331 QMessageBox.warning(this, tr("SDI"), | |
332 tr("Cannot read file " ~ | |
333 fileName ~ ":\n" ~ | |
334 file.errorString ~ ".")); | |
335 return; | |
336 } | |
337 | |
338 scope inStream = new QTextStream(file); | |
339 QApplication.setOverrideCursor(new QCursor(Qt.WaitCursor)); | |
340 textEdit.setPlainText(inStream.readAll()); | |
341 QApplication.restoreOverrideCursor(); | |
342 | |
343 setCurrentFile(fileName); | |
344 statusBar.showMessage(tr("File loaded"), 2000); | |
345 } | |
346 | |
347 bool saveFile(string fileName) | |
348 { | |
349 scope file = new QFile(fileName); | |
350 if (!file.open(QFile.WriteOnly | QFile.Text)) { | |
351 QMessageBox.warning(this, tr("SDI"), | |
352 tr("Cannot write file " ~ | |
353 fileName ~ ":\n" ~ | |
354 file.errorString ~ ".")); | |
355 return false; | |
356 } | |
357 | |
358 scope outStream = new QTextStream(file); | |
359 QApplication.setOverrideCursor(new QCursor(Qt.WaitCursor)); | |
360 outStream.writeString(textEdit.toPlainText()); | |
361 QApplication.restoreOverrideCursor(); | |
362 | |
363 setCurrentFile(fileName); | |
364 statusBar.showMessage("Saved '" ~ fileName ~ "'", 2000); | |
365 return true; | |
366 } | |
367 | |
368 void setCurrentFile(string fileName) | |
369 { | |
370 static int sequenceNumber = 1; | |
371 | |
372 isUntitled = fileName == null; | |
373 if (isUntitled) { | |
374 version(Tango) | |
375 curFile = tr("document" ~ Int.toString(sequenceNumber++) ~ ".txt"); | |
376 else | |
377 curFile = tr("document" ~ to!(string)(sequenceNumber++) ~ ".txt"); | |
378 } else { | |
379 scope qfi = new QFileInfo(fileName); | |
380 curFile = qfi.canonicalFilePath; | |
381 } | |
382 | |
383 textEdit.document().setModified(false); | |
384 setWindowModified(false); | |
385 | |
386 setWindowTitle(strippedName(curFile) ~ "[*] - " ~ tr("SDI")); | |
387 } | |
388 | |
389 string strippedName(string fullFileName) | |
390 { | |
391 scope qfi = new QFileInfo(fullFileName); | |
392 return qfi.fileName(); | |
393 } | |
394 | |
395 MainWindow findMainWindow(string fileName) | |
396 { | |
397 scope qfi = new QFileInfo(fileName); | |
398 string canonicalFilePath = qfi.canonicalFilePath(); | |
399 | |
400 foreach (QWidget widget; QApplication.topLevelWidgets) { | |
401 MainWindow mainWin = cast(MainWindow)(widget); | |
402 if (mainWin && mainWin.curFile == canonicalFilePath) | |
403 return mainWin; | |
404 } | |
405 return null; | |
406 } | |
407 | |
408 QTextEdit textEdit; | |
409 string curFile; | |
410 bool isUntitled; | |
411 | |
412 QMenu fileMenu; | |
413 QMenu editMenu; | |
414 QMenu helpMenu; | |
415 QToolBar fileToolBar; | |
416 QToolBar editToolBar; | |
417 | |
418 QAction newAct; | |
419 QAction openAct; | |
420 QAction saveAct; | |
421 QAction saveAsAct; | |
422 QAction closeAct; | |
423 QAction exitAct; | |
424 QAction cutAct; | |
425 QAction copyAct; | |
426 QAction pasteAct; | |
427 QAction aboutAct; | |
428 QAction aboutQtAct; | |
429 }; |