]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI_builtins.cc
drawContent is no more
[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 <QMessageBox>
30 #include <QPixmap>
31 #include <QInputDialog>
32
33 #include <ycp/YCPTerm.h>
34 #define y2log_component "qt-ui"
35 #include <ycp/y2log.h>
36
37 #include "YQUI.h"
38 #include "YEvent.h"
39 #include "YMacroRecorder.h"
40 #include "YUISymbols.h"
41 #include "YQDialog.h"
42 #include "YQSignalBlocker.h"
43
44 #include "utf8.h"
45 #include "YQi18n.h"
46
47 #include <X11/Xlib.h>
48
49
50 #define DEFAULT_MACRO_FILE_NAME         "macro.ycp"
51
52
53
54 YCPString
55 YQUI::glyph( const YCPSymbol & glyphSymbol )
56 {
57     string sym = glyphSymbol->symbol();
58     QChar unicodeChar;
59
60     // Hint: Use 'xfd' to view characters available in the Unicode font.
61
62     if      ( sym == YUIGlyph_ArrowLeft         )       unicodeChar = QChar( 0x2190 );
63     else if ( sym == YUIGlyph_ArrowRight        )       unicodeChar = QChar( 0x2192 );
64     else if ( sym == YUIGlyph_ArrowUp           )       unicodeChar = QChar( 0x2191 );
65     else if ( sym == YUIGlyph_ArrowDown         )       unicodeChar = QChar( 0x2193 );
66     else if ( sym == YUIGlyph_CheckMark         )       unicodeChar = QChar( 0x2714 );
67     else if ( sym == YUIGlyph_BulletArrowRight  )       unicodeChar = QChar( 0x279c );
68     else if ( sym == YUIGlyph_BulletCircle      )       unicodeChar = QChar( 0x274d );
69     else if ( sym == YUIGlyph_BulletSquare      )       unicodeChar = QChar( 0x274f );
70     else return YCPString( "" );
71
72     QString qstr( unicodeChar );
73
74     return YCPString( toUTF8( qstr ) );
75 }
76
77
78 YCPValue YQUI::runPkgSelection( YWidget * packageSelector )
79 {
80     y2milestone( "Running package selection..." );
81     _wm_close_blocked           = true;
82     _auto_activate_dialogs      = false;
83
84     YCPValue input = YCPVoid();
85
86     try
87     {
88         input = evaluateUserInput();
89     }
90     catch (const std::exception & e)
91     {
92         y2error( "Caught std::exception: %s", e.what() );
93         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
94     }
95     catch (...)
96     {
97         y2error( "Caught unspecified exception." );
98         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
99     }
100
101     _auto_activate_dialogs      = true;
102     _wm_close_blocked           = false;
103     y2milestone( "Package selection done - returning %s", input->toString().c_str() );
104
105     return input;
106 }
107
108
109 void YQUI::makeScreenShot( std::string stl_filename )
110 {
111
112     //
113     // Grab the pixels off the screen
114     //
115
116     QWidget * dialog = (QWidget *) YDialog::currentDialog()->widgetRep();
117     QPixmap screenShot = QPixmap::grabWindow( dialog->winId() );
118     //FIXME XSync( dialog->x11Display(), false );
119     QString fileName ( stl_filename.c_str() );
120     bool interactive = false;
121
122     if ( fileName.isEmpty() )
123     {
124         interactive = true;
125
126         // Open a file selection box. Figure out a reasonable default
127         // directory / file name.
128
129         if ( screenShotNameTemplate.isEmpty() )
130         {
131             //
132             // Initialize screen shot directory
133             //
134
135             QString home = QDir::homePath();
136             char * ssdir = getenv("Y2SCREENSHOTS");
137             QString dir  = ssdir ? ssdir : "yast2-screen-shots";
138
139             if ( home == "/" )
140             {
141                 // Special case: $HOME is not set. This is normal in the inst-sys.
142                 // In this case, rather than simply dumping all screen shots into
143                 // /tmp which is world-writable, let's try to create a subdirectory
144                 // below /tmp with restrictive permissions.
145                 // If that fails, trust nobody - in particular, do not suggest /tmp
146                 // as the default in the file selection box.
147
148                 dir = "/tmp/" + dir;
149
150                 if ( mkdir( qPrintable(dir), 0700 ) == -1 )
151                     dir = "";
152             }
153             else
154             {
155                 // For all others let's create a directory ~/yast2-screen-shots and
156                 // simply ignore if this is already present. This gives the user a
157                 // chance to create symlinks to a better location if he wishes so.
158
159                 dir = home + "/" + dir;
160                 (void) mkdir( qPrintable(dir), 0750 );
161             }
162
163             screenShotNameTemplate = dir + "/%s-%03d.png";
164         }
165
166
167         //
168         // Figure out a file name
169         //
170
171         const char * baseName = moduleName();
172         if ( ! baseName ) baseName = "scr";
173         int no = screenShotNo[ baseName ];
174         fileName.sprintf( qPrintable(screenShotNameTemplate), baseName, no );
175         y2debug( "screenshot: %s", qPrintable(fileName) );
176
177         {
178             YQSignalBlocker sigBlocker( &_user_input_timer );
179
180             fileName = askForSaveFileName( fileName, QString( "*.png" ) , _( "Save screen shot to..." ) );
181         }
182
183         if ( fileName.isEmpty() )
184         {
185             y2debug( "Save screen shot canceled by user" );
186             return;
187         }
188
189         screenShotNo.insert( baseName, ++no );
190     } // if fileName.isEmpty()
191
192
193     //
194     // Actually save the screen shot
195     //
196
197     y2debug( "Saving screen shot to %s", qPrintable(fileName) );
198     bool success = screenShot.save( fileName, "PNG" );
199
200     if ( ! success )
201     {
202         y2error( "Couldn't save screen shot %s", qPrintable(fileName) );
203
204         if ( interactive )
205         {
206             QMessageBox::warning( 0,                                    // parent
207                                   "Error",                              // caption
208                                   QString( "Couldn't save screen shot\nto %1" ).arg( fileName ),
209                                   QMessageBox::Ok | QMessageBox::Default,       // button0
210                                   Qt::NoButton,                         // button1
211                                   Qt::NoButton );                       // button2
212         }
213     }
214
215     if ( recordingMacro() )
216     {
217         macroRecorder->beginBlock();
218         YDialog::currentDialog()->saveUserInput( macroRecorder );
219         macroRecorder->recordMakeScreenShot( true, qPrintable(fileName) );
220         macroRecorder->recordUserInput( YCPVoid() );
221         macroRecorder->endBlock();
222     }
223 }
224
225
226 void YQUI::askSaveLogs()
227 {
228     QString fileName = askForSaveFileName( "/tmp/y2logs.tgz",                   // startWith
229                                            "*.tgz *.tar.gz",                    // filter
230                                            "Save y2logs to..." );               // headline
231
232     if ( ! fileName.isEmpty() )
233     {
234         QString saveLogsCommand = "/sbin/save_y2logs";
235
236         if ( access( saveLogsCommand.toAscii(), X_OK ) == 0 )
237         {
238             saveLogsCommand += " '" + fileName + "'";
239             y2milestone( "Saving y2logs: %s", qPrintable(saveLogsCommand) );
240             int result = system( qPrintable(saveLogsCommand) );
241
242             if ( result != 0 )
243             {
244                 y2error( "Error saving y2logs: \"%s\" exited with %d",
245                          qPrintable(saveLogsCommand), result );
246                 QMessageBox::warning( 0,                                        // parent
247                                       "Error",                                  // caption
248                                       QString( "Couldn't save y2logs to %1 - "
249                                                "exit code %2" ).arg( fileName ).arg( result ),
250                                       QMessageBox::Ok | QMessageBox::Default,   // button0
251                                       QMessageBox::NoButton,                    // button1
252                                       QMessageBox::NoButton );                  // button2
253             }
254             else
255             {
256                 y2milestone( "y2logs saved to %s", qPrintable(fileName) );
257             }
258         }
259         else
260         {
261             y2error( "Error saving y2logs: Command %s not found",
262                      qPrintable(saveLogsCommand) );
263
264             QMessageBox::warning( 0,                                            // parent
265                                   "Error",                                      // caption
266                                   QString( "Couldn't save y2logs to %1:\n"
267                                            "Command %2 not found" ).arg( fileName ).arg( saveLogsCommand ),
268                                   QMessageBox::Ok | QMessageBox::Default,       // button0
269                                   QMessageBox::NoButton,                        // button1
270                                   QMessageBox::NoButton );                      // button2
271         }
272     }
273 }
274
275
276 void YQUI::askConfigureLogging()
277 {
278     bool okButtonPressed = false;
279     QStringList items;
280     items << "Debug logging off"
281           << "Debug logging on";
282
283     QString result = QInputDialog::getItem( _main_win,
284                                           tr("YaST2 Logging"),
285                                           tr("Configure YaST2 Logging:"),
286                                           items, 0, get_log_debug() ? 1 : 0, &okButtonPressed);
287     if ( okButtonPressed )
288     {
289         set_log_debug( result.endsWith( "on" ) );
290         y2milestone( "Changing logging: %s - %s", qPrintable(result),
291                      get_log_debug() ? "y2debug on" : "y2debug off" );
292     }
293 }
294
295
296 void YQUI::toggleRecordMacro()
297 {
298     if ( recordingMacro() )
299     {
300         stopRecordMacro();
301         normalCursor();
302
303         QMessageBox::information( 0,                                            // parent
304                                   "YaST2 Macro Recorder",                       // caption
305                                   "Macro recording done.",                      // text
306                                   QMessageBox::Ok | QMessageBox::Default,       // button0
307                                   QMessageBox::NoButton,                        // button1
308                                   QMessageBox::NoButton );                      // button2
309     }
310     else
311     {
312         normalCursor();
313
314         QString filename =
315             QFileDialog::getSaveFileName( 0,
316                                           "Select Macro File to Record to",
317                                           DEFAULT_MACRO_FILE_NAME,              // startWith
318                                           "*.ycp"                             // filter
319                                           );
320
321         if ( ! filename.isEmpty() )     // file selection dialog has been cancelled
322         {
323             recordMacro( qPrintable(filename) );
324         }
325     }
326 }
327
328
329 void YQUI::askPlayMacro()
330 {
331     normalCursor();
332
333     QString filename =
334         QFileDialog::getOpenFileName( 0,
335                                       "Select Macro File to Play",
336                                       DEFAULT_MACRO_FILE_NAME,          // startWith
337                                       "*.ycp" );
338     busyCursor();
339
340     if ( ! filename.isEmpty() ) // file selection dialog has been cancelled
341     {
342         playMacro( qPrintable(filename) );
343
344         // Do special magic to get out of any UserInput() loop right now
345         // without doing any harm - otherwise this would hang until the next
346         // mouse click on a PushButton etc.
347
348         sendEvent( new YEvent() );
349
350         if ( _do_exit_loop )
351         {
352             _eventLoop->exit();
353         }
354     }
355 }
356
357
358
359 YCPValue YQUI::askForExistingDirectory( const YCPString & startDir,
360                                          const YCPString & headline )
361 {
362     normalCursor();
363
364     QString dir_name =
365         QFileDialog::getExistingDirectory( _main_win,
366                                            fromUTF8( headline->value() ),
367                                            fromUTF8( startDir->value() ) );
368     busyCursor();
369
370     if ( dir_name.isEmpty() )   // this includes dir_name.isNull()
371         return YCPVoid();       // nothing selected -> return 'nil'
372
373     return YCPString( toUTF8( dir_name ) );
374 }
375
376
377 YCPValue YQUI::askForExistingFile( const YCPString & startWith,
378                                    const YCPString & filter,
379                                    const YCPString & headline )
380 {
381     normalCursor();
382
383     QString file_name =
384         QFileDialog::getOpenFileName( _main_win,                        // parent
385                                       fromUTF8( headline->value() ),
386                                       fromUTF8( startWith->value() ),
387                                       fromUTF8( filter->value() ) );
388     busyCursor();
389
390     if ( file_name.isEmpty() )  // this includes file_name.isNull()
391         return YCPVoid();       // nothing selected -> return 'nil'
392
393     return YCPString( toUTF8( file_name ) );
394 }
395
396
397 YCPValue YQUI::askForSaveFileName( const YCPString & startWith,
398                                    const YCPString & filter,
399                                    const YCPString & headline )
400 {
401     normalCursor();
402
403     QString file_name = askForSaveFileName( fromUTF8( startWith->value() ),
404                                             fromUTF8( filter->value() ),
405                                             fromUTF8( headline->value() ) );
406     busyCursor();
407
408     if ( file_name.isEmpty() )          // this includes file_name.isNull()
409         return YCPVoid();               // nothing selected -> return 'nil'
410
411     return YCPString( toUTF8( file_name ) );
412 }
413
414
415
416 QString YQUI::askForSaveFileName( const QString & startWith,
417                                   const QString & filter,
418                                   const QString & headline )
419 {
420     QString file_name;
421     bool try_again = false;
422
423     do
424     {
425         // Leave the mouse cursor alone - this function might be called from
426         // some other widget, not only from UI::AskForSaveFileName().
427
428         file_name = QFileDialog::getSaveFileName( _main_win,
429                                                   headline,
430                                                   startWith,
431                                                   filter );
432
433         if ( file_name.isEmpty() )      // this includes file_name.isNull()
434             return QString::null;
435
436
437         if ( access( qPrintable(file_name), F_OK ) == 0 )    // file exists?
438         {
439             QString msg;
440
441             if ( access( qPrintable(file_name), W_OK ) == 0 )
442             {
443                 // Confirm if the user wishes to overwrite an existing file
444                 msg = ( _( "%1 exists! Really overwrite?" ) ).arg( file_name );
445             }
446             else
447             {
448                 // Confirm if the user wishes to overwrite a write-protected file %1
449                 msg = ( _( "%1 exists and is write-protected!\nReally overwrite?" ) ).arg( file_name );
450             }
451
452             int button_no = QMessageBox::information( _main_win,
453                                                       // Window title for confirmation dialog
454                                                       _( "Confirm"   ),
455                                                       msg,
456                                                       _( "C&ontinue" ),
457                                                       _( "&Cancel"   ) );
458             try_again = ( button_no != 0 );
459         }
460
461     } while ( try_again );
462
463     return file_name;
464 }
465
466
467 // EOF