]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI_builtins.cc
don't create QObjects in ycp thread - make timeouts work
[duncan/yast2-qt4.git] / src / YQUI_builtins.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:         YUIQt_builtins.cc
14
15   Author:       Stefan Hundhammer <sh@suse.de>
16
17   Textdomain    "packages-qt"
18
19 /-*/
20
21 #define USE_QT_CURSORS          1
22 #define FORCE_UNICODE_FONT      0
23
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include <QCursor>
28 #include <QFileDialog>
29 #include <QX11Info>
30 #include <QMessageBox>
31 #include <QPixmap>
32 #include <QInputDialog>
33 #include <qdir.h>
34
35 #define y2log_component "qt-ui"
36 #include <ycp/y2log.h>
37
38 #include "YQUI.h"
39 #include "YEvent.h"
40 #include "YMacroRecorder.h"
41 #include "YUISymbols.h"
42 #include "YQDialog.h"
43 #include "YQSignalBlocker.h"
44 #include "YQApplication.h"
45
46 #include "utf8.h"
47 #include "YQi18n.h"
48
49 #include <X11/Xlib.h>
50
51
52 #define DEFAULT_MACRO_FILE_NAME         "macro.ycp"
53
54
55
56 YCPString
57 YQUI::glyph( const YCPSymbol & glyphSymbol )
58 {
59     string sym = glyphSymbol->symbol();
60     QChar unicodeChar;
61
62     // Hint: Use 'xfd' to view characters available in the Unicode font.
63
64     if      ( sym == YUIGlyph_ArrowLeft         )       unicodeChar = QChar( 0x2190 );
65     else if ( sym == YUIGlyph_ArrowRight        )       unicodeChar = QChar( 0x2192 );
66     else if ( sym == YUIGlyph_ArrowUp           )       unicodeChar = QChar( 0x2191 );
67     else if ( sym == YUIGlyph_ArrowDown         )       unicodeChar = QChar( 0x2193 );
68     else if ( sym == YUIGlyph_CheckMark         )       unicodeChar = QChar( 0x2714 );
69     else if ( sym == YUIGlyph_BulletArrowRight  )       unicodeChar = QChar( 0x279c );
70     else if ( sym == YUIGlyph_BulletCircle      )       unicodeChar = QChar( 0x274d );
71     else if ( sym == YUIGlyph_BulletSquare      )       unicodeChar = QChar( 0x274f );
72     else return YCPString( "" );
73
74     QString qstr( unicodeChar );
75
76     return YCPString( toUTF8( qstr ) );
77 }
78
79
80 YCPValue YQUI::runPkgSelection( YWidget * packageSelector )
81 {
82     y2milestone( "Running package selection..." );
83     YCPValue input = YCPVoid();
84
85     try
86     {
87         input = evaluateUserInput();
88     }
89     catch (const std::exception & e)
90     {
91         y2error( "Caught std::exception: %s", e.what() );
92         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
93     }
94     catch (...)
95     {
96         y2error( "Caught unspecified exception." );
97         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
98     }
99
100     y2milestone( "Package selection done - returning %s", input->toString().c_str() );
101
102     return input;
103 }
104
105
106 void YQUI::makeScreenShot( std::string stl_filename )
107 {
108
109     //
110     // Grab the pixels off the screen
111     //
112
113     QWidget * dialog = (QWidget *) YDialog::currentDialog()->widgetRep();
114     QPixmap screenShot = QPixmap::grabWindow( dialog->winId() );
115     XSync( QX11Info::display(), false );
116     QString fileName ( stl_filename.c_str() );
117     bool interactive = false;
118
119     if ( fileName.isEmpty() )
120     {
121         interactive = true;
122
123         // Open a file selection box. Figure out a reasonable default
124         // directory / file name.
125
126         if ( screenShotNameTemplate.isEmpty() )
127         {
128             //
129             // Initialize screen shot directory
130             //
131
132             QString home = QDir::homePath();
133             char * ssdir = getenv("Y2SCREENSHOTS");
134             QString dir  = ssdir ? ssdir : "yast2-screen-shots";
135
136             if ( home == "/" )
137             {
138                 // Special case: $HOME is not set. This is normal in the inst-sys.
139                 // In this case, rather than simply dumping all screen shots into
140                 // /tmp which is world-writable, let's try to create a subdirectory
141                 // below /tmp with restrictive permissions.
142                 // If that fails, trust nobody - in particular, do not suggest /tmp
143                 // as the default in the file selection box.
144
145                 dir = "/tmp/" + dir;
146
147                 if ( mkdir( qPrintable(dir), 0700 ) == -1 )
148                     dir = "";
149             }
150             else
151             {
152                 // For all others let's create a directory ~/yast2-screen-shots and
153                 // simply ignore if this is already present. This gives the user a
154                 // chance to create symlinks to a better location if he wishes so.
155
156                 dir = home + "/" + dir;
157                 (void) mkdir( qPrintable(dir), 0750 );
158             }
159
160             screenShotNameTemplate = dir + "/%s-%03d.png";
161         }
162
163
164         //
165         // Figure out a file name
166         //
167
168         const char * baseName = moduleName();
169         if ( ! baseName ) baseName = "scr";
170         int no = screenShotNo[ baseName ];
171         fileName.sprintf( qPrintable(screenShotNameTemplate), baseName, no );
172         y2debug( "screenshot: %s", qPrintable(fileName) );
173
174         {
175             YQSignalBlocker sigBlocker( _user_input_timer );
176
177             fileName = YQApplication::askForSaveFileName( fileName,
178                                                           QString( "*.png" ) ,
179                                                           _( "Save screen shot to..." ) );
180         }
181
182         if ( fileName.isEmpty() )
183         {
184             y2debug( "Save screen shot canceled by user" );
185             return;
186         }
187
188         screenShotNo.insert( baseName, ++no );
189     } // if fileName.isEmpty()
190
191
192     //
193     // Actually save the screen shot
194     //
195
196     y2debug( "Saving screen shot to %s", qPrintable(fileName) );
197     bool success = screenShot.save( fileName, "PNG" );
198
199     if ( ! success )
200     {
201         y2error( "Couldn't save screen shot %s", qPrintable(fileName) );
202
203         if ( interactive )
204         {
205             QMessageBox::warning( 0,                                    // parent
206                                   "Error",                              // caption
207                                   QString( "Couldn't save screen shot\nto %1" ).arg( fileName ),
208                                   QMessageBox::Ok | QMessageBox::Default,       // button0
209                                   Qt::NoButton,                         // button1
210                                   Qt::NoButton );                       // button2
211         }
212     }
213
214     if ( recordingMacro() )
215     {
216         macroRecorder->beginBlock();
217         YDialog::currentDialog()->saveUserInput( macroRecorder );
218         macroRecorder->recordMakeScreenShot( true, qPrintable(fileName) );
219         macroRecorder->recordUserInput( YCPVoid() );
220         macroRecorder->endBlock();
221     }
222 }
223
224
225 void YQUI::askSaveLogs()
226 {
227     QString fileName = YQApplication::askForSaveFileName( QString( "/tmp/y2logs.tgz" ),         // startWith
228                                                           QString( "*.tgz *.tar.gz"  ),         // filter
229                                                           QString( "Save y2logs to..."  ) );    // headline
230
231     if ( ! fileName.isEmpty() )
232     {
233         QString saveLogsCommand = "/sbin/save_y2logs";
234
235         if ( access( saveLogsCommand.toAscii(), X_OK ) == 0 )
236         {
237             saveLogsCommand += " '" + fileName + "'";
238             y2milestone( "Saving y2logs: %s", qPrintable(saveLogsCommand) );
239             int result = system( qPrintable(saveLogsCommand) );
240
241             if ( result != 0 )
242             {
243                 y2error( "Error saving y2logs: \"%s\" exited with %d",
244                          qPrintable(saveLogsCommand), result );
245                 QMessageBox::warning( 0,                                        // parent
246                                       "Error",                                  // caption
247                                       QString( "Couldn't save y2logs to %1 - "
248                                                "exit code %2" ).arg( fileName ).arg( result ),
249                                       QMessageBox::Ok | QMessageBox::Default,   // button0
250                                       QMessageBox::NoButton,                    // button1
251                                       QMessageBox::NoButton );                  // button2
252             }
253             else
254             {
255                 y2milestone( "y2logs saved to %s", qPrintable(fileName) );
256             }
257         }
258         else
259         {
260             y2error( "Error saving y2logs: Command %s not found",
261                      qPrintable(saveLogsCommand) );
262
263             QMessageBox::warning( 0,                                            // parent
264                                   "Error",                                      // caption
265                                   QString( "Couldn't save y2logs to %1:\n"
266                                            "Command %2 not found" ).arg( fileName ).arg( saveLogsCommand ),
267                                   QMessageBox::Ok | QMessageBox::Default,       // button0
268                                   QMessageBox::NoButton,                        // button1
269                                   QMessageBox::NoButton );                      // button2
270         }
271     }
272 }
273
274
275 void YQUI::askConfigureLogging()
276 {
277     bool okButtonPressed = false;
278     QStringList items;
279     items << "Debug logging off"
280           << "Debug logging on";
281
282     QString result = QInputDialog::getItem( _main_win,
283                                             _("YaST2 Logging"),
284                                             _("Configure YaST2 Logging:"),
285                                             items, 0, get_log_debug() ? 1 : 0, &okButtonPressed);
286     if ( okButtonPressed )
287     {
288         set_log_debug( result.endsWith( "on" ) );
289         y2milestone( "Changing logging: %s - %s", qPrintable(result),
290                      get_log_debug() ? "y2debug on" : "y2debug off" );
291     }
292 }
293
294
295 void YQUI::toggleRecordMacro()
296 {
297     if ( recordingMacro() )
298     {
299         stopRecordMacro();
300         normalCursor();
301
302         QMessageBox::information( 0,                                            // parent
303                                   "YaST2 Macro Recorder",                       // caption
304                                   "Macro recording done.",                      // text
305                                   QMessageBox::Ok | QMessageBox::Default,       // button0
306                                   QMessageBox::NoButton,                        // button1
307                                   QMessageBox::NoButton );                      // button2
308     }
309     else
310     {
311         normalCursor();
312
313         QString filename =
314             QFileDialog::getSaveFileName( 0,
315                                           "Select Macro File to Record to",
316                                           DEFAULT_MACRO_FILE_NAME,              // startWith
317                                           "*.ycp"                             // filter
318                                           );
319
320         if ( ! filename.isEmpty() )     // file selection dialog has been cancelled
321         {
322             recordMacro( qPrintable(filename) );
323         }
324     }
325 }
326
327
328 void YQUI::askPlayMacro()
329 {
330     normalCursor();
331
332     QString filename =
333         QFileDialog::getOpenFileName( 0,
334                                       "Select Macro File to Play",
335                                       DEFAULT_MACRO_FILE_NAME,          // startWith
336                                       "*.ycp" );
337     busyCursor();
338
339     if ( ! filename.isEmpty() ) // file selection dialog has been cancelled
340     {
341         playMacro( qPrintable(filename) );
342
343         // Do special magic to get out of any UserInput() loop right now
344         // without doing any harm - otherwise this would hang until the next
345         // mouse click on a PushButton etc.
346
347         sendEvent( new YEvent() );
348
349         if ( _do_exit_loop )
350         {
351             _eventLoop->exit();
352         }
353     }
354 }
355
356
357 // EOF