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