Coding between Mouse and Keyboard, Part II
Basically, we won't do much more than substitute the qWarning()'s saying “not yet implemented” in editor.cpp with reasonable functionality, using our favourite text editor. If the Designer's built-in code editor suits your needs, you don't have to worry about subclassing, but compiling and debugging becomes more painful, so we decided against it.
Listing 1 shows all of editor.h; Listing 2 is an excerpt from editor.cpp. All listings are available from the Linux Journal FTP site [ftp.linuxjournal.com/pub/lj/listings/issue102/4722.tgz].
Apart from the four slots left to implement, we re-implement the closeEvent(), a function that's called when a widget is closed, because we want the user to confirm the closing of an editor window so as not to unexpectedly lose data. For clarity reasons, the relevant user dialog is implemented in a separate function, saveAndContinue().
Also, we introduce two class variables: fileName, to store the filename of the currently edited file, and editField, to hold a copy of the QTextEdit widget. Providing these variables with initial values is the only task for the Editor constructor.
Another easy task is to implement the fileNew() slot. It creates a new Editor window and shows it. This is why we don't make the first editor window the application's main widget: if we did, closing the first editor window would make all other windows close too.
But what happens when the user closes a window or the entire application? The re-implemented closeEvent() calls saveAndContinue() with one argument: the message that should be displayed to users when they decide to abort the closing process (line 159). As with all text strings, we embrace it with tr() to make localization possible. If saveAndContinue() returns a “yes, continue”, the close event is accepted; otherwise the event is dismissed.
If the user has chosen a filename for the editor content or entered some text into the QTextEdit widget, it is safe to assume that he or she might want to keep the work. In this case saveAndContinue() brings up a message box using the filename as the window caption that asks: Save filename? Three reply buttons are provided: Yes, No and Cancel. The slightly copious notation with the %1 placeholder for the content of fileName is important for internationalization: other languages order words differently, and the translator must have a chance to place the filename elsewhere, say the beginning of the phrase.
If the Yes button was pressed (line 181) the editor content is saved under the given name. If no filename has been set, fileSaveAs() asks for a filename before storing. If the answer is No, all unsaved changes are lost. The user is informed about this in the status bar for 2,000 milliseconds (line 187). The Cancel button shows the abort message in the status bar, and saveAndContinue() returns a “no, don't continue” (line 194). In the case where no filename and no editor content are present, no message box appears. The return value then is a TRUE, “do continue anyway” (line 201).
saveAndContinue also is called from the fileOpen() slot. If the editor window contains text or if a filename was defined previously, the user has the chance to save it prior to opening another file in this window.
Whether saved or not, clearing the editor content and resetting the window caption makes the user aware that the old editor content is gone. With the help of a file dialog presenting the content of the current (.) directory, the user gets the chance to choose a new file.
With the tr() functions around each text string, we're able to release the program in other languages. All this step requires are some modifications of the main() function and the actual translation. The latter is easily accomplished using Qt Linguist (Figure 2). But before you or another translator gets started, we have to obtain the text strings to be translated.
First we add another variable, TRANSLATIONS, to the *.pro file:
TRANSLATIONS = ljedit_de.ts \ ljedit_no.ts
This example states that the application is bound for translation into German (ljedit_de.ts) and Norwegian (ljedit_no.ts). It is quite important that the base name of the file containing the translation ends with a locale abbreviation like “de” or “no”.
Once you have selected the desired translation language(s) for the application, typing lupdate lj-article.pro creates two XML files that can be loaded into linguist. The translator now translates each string and switches the yellow question mark to a green tick when completed. The task has been fulfilled as soon as the Scope window (on the left-hand side of Figure 2) reveals that all of the classes have been translated fully.
A professional translator will compile phrase books of common phrase-translation pairs before actually starting with the translation of a program. As Linguist currently doesn't let users copy translated strings from a program directly into phrase books, the effort of compiling a phrase book is too high for those who do not translate frequently. This is a pity because phrase books support consistent usage of phrases within an application or even throughout an entire range of programs. However, even without phrase books, Linguist offers quality control switches. Validation®Accelerators—if on—ensures that accelerator keys (marked with an &) are not forgotten under translation. Validation®Ending Punctuation, on the other hand, checks whether the translated string ends with the same punctuation mark as the original.
When the last translated phrase is saved, File®Release... compiles the translations into a *.qm binary file that can be used by the program. To release an entire set of translated *.ts files, lrelease lj-article.pro can be used instead. If the code is changed afterward, a fresh lupdate run integrates the relevant changes with the *.ts files listed in the project file, and lrelease updates the binary version.
Listing 3 shows the internationalized main(). New is the inclusion of qtranslator.h and qtextcodec.h. Depending on the locale used (as defined by the environment variable LANG), the base name of the translation file is compiled (line 13). If LANG is set to, for example, de or de_DE, the application looks for a file named ljedit_de or ljedit_de.qm in /local/lib. If it can't be found there, the original language version is used. Unfortunately, there is no simple way to search multiple directories and/or avoid hard-coded directory names.
If a translation file is found, the QTranslator object loads it, and it is installed to serve the application (line 15). A German version of ljedit is shown in Figure 3.
Patricia Jung (email@example.com) has been a system administrator, technical writer and editor, and as such, is happy to have the privilege of dealing with Linux/UNIX exclusively.
Practical Task Scheduling Deployment
July 20, 2016 12:00 pm CDT
One of the best things about the UNIX environment (aside from being stable and efficient) is the vast array of software tools available to help you do your job. Traditionally, a UNIX tool does only one thing, but does that one thing very well. For example, grep is very easy to use and can search vast amounts of data quickly. The find tool can find a particular file or files based on all kinds of criteria. It's pretty easy to string these tools together to build even more powerful tools, such as a tool that finds all of the .log files in the /home directory and searches each one for a particular entry. This erector-set mentality allows UNIX system administrators to seem to always have the right tool for the job.
Cron traditionally has been considered another such a tool for job scheduling, but is it enough? This webinar considers that very question. The first part builds on a previous Geek Guide, Beyond Cron, and briefly describes how to know when it might be time to consider upgrading your job scheduling infrastructure. The second part presents an actual planning and implementation framework.
Join Linux Journal's Mike Diehl and Pat Cameron of Help Systems.
Free to Linux Journal readers.Register Now!
- SUSE LLC's SUSE Manager
- Google's SwiftShader Released
- Murat Yener and Onur Dundar's Expert Android Studio (Wrox)
- My +1 Sword of Productivity
- Managing Linux Using Puppet
- Non-Linux FOSS: Caffeine!
- SuperTuxKart 0.9.2 Released
- Parsing an RSS News Feed with a Bash Script
- Rogue Wave Software's Zend Server
- Doing for User Space What We Did for Kernel Space
With all the industry talk about the benefits of Linux on Power and all the performance advantages offered by its open architecture, you may be considering a move in that direction. If you are thinking about analytics, big data and cloud computing, you would be right to evaluate Power. The idea of using commodity x86 hardware and replacing it every three years is an outdated cost model. It doesn’t consider the total cost of ownership, and it doesn’t consider the advantage of real processing power, high-availability and multithreading like a demon.
This ebook takes a look at some of the practical applications of the Linux on Power platform and ways you might bring all the performance power of this open architecture to bear for your organization. There are no smoke and mirrors here—just hard, cold, empirical evidence provided by independent sources. I also consider some innovative ways Linux on Power will be used in the future.Get the Guide