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