Win_GParted.cc 130 KB
Newer Older
1
/* Copyright (C) 2004 Bart
2
 * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Curtis Gedak
Bart Hakvoort's avatar
Bart Hakvoort committed
3 4 5 6 7 8 9 10 11
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
Bart Hakvoort's avatar
Bart Hakvoort committed
13 14
 *
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
Bart Hakvoort's avatar
Bart Hakvoort committed
16
 */
17 18

#include "Win_GParted.h"
19
#include "Device.h"
20 21
#include "Dialog_Progress.h"
#include "DialogFeatures.h"
22
#include "DialogPasswordEntry.h"
23 24 25 26 27 28 29 30 31
#include "Dialog_Disklabel.h"
#include "Dialog_Rescue_Data.h"
#include "Dialog_Partition_Resize_Move.h"
#include "Dialog_Partition_Copy.h"
#include "Dialog_Partition_New.h"
#include "Dialog_Partition_Info.h"
#include "Dialog_FileSystem_Label.h"
#include "Dialog_Partition_Name.h"
#include "DialogManageFlags.h"
32
#include "GParted_Core.h"
33
#include "MenuHelpers.h"
34 35 36 37 38 39 40 41 42 43 44 45
#include "Mount_Info.h"
#include "OperationCopy.h"
#include "OperationCheck.h"
#include "OperationCreate.h"
#include "OperationDelete.h"
#include "OperationFormat.h"
#include "OperationResizeMove.h"
#include "OperationChangeUUID.h"
#include "OperationLabelFileSystem.h"
#include "OperationNamePartition.h"
#include "Partition.h"
#include "PartitionVector.h"
46
#include "PasswordRAMStore.h"
47
#include "LVM2_PV_Info.h"
48
#include "Utils.h"
49
#include "../config.h"
Bart Hakvoort's avatar
Bart Hakvoort committed
50

51
#include <string.h>
52
#include <gtkmm/cssprovider.h>
53
#include <gtkmm/aboutdialog.h>
Bart Hakvoort's avatar
p  
Bart Hakvoort committed
54
#include <gtkmm/messagedialog.h>
55
#include <gtkmm/radiobuttongroup.h>
56
#include <gtkmm/radiomenuitem.h>
57
#include <gtkmm/main.h>
58
#include <gtkmm/separator.h>
59
#include <gtkmm/grid.h>
60
#include <glibmm/ustring.h>
61 62 63 64
#include <glibmm/miscutils.h>
#include <glibmm/shell.h>
#include <glibmm/main.h>

65

Bart Hakvoort's avatar
Bart Hakvoort committed
66 67
namespace GParted
{
68
	
69
Win_GParted::Win_GParted( const std::vector<Glib::ustring> & user_devices )
Bart Hakvoort's avatar
Bart Hakvoort committed
70
{
71
	copied_partition = NULL;
72
	selected_partition_ptr = NULL;
Bart Hakvoort's avatar
Bart Hakvoort committed
73
	new_count = 1;
74
	current_device = 0 ;
75
	OPERATIONSLIST_OPEN = true ;
76
	gparted_core .set_user_devices( user_devices ) ;
77
	
78 79 80 81 82 83 84
	TOOLBAR_NEW =
	TOOLBAR_DEL =
	TOOLBAR_RESIZE_MOVE =
	TOOLBAR_COPY =
	TOOLBAR_PASTE =
	TOOLBAR_UNDO =
	TOOLBAR_APPLY = -1;
85

Bart Hakvoort's avatar
Bart Hakvoort committed
86
	//==== GUI =========================
87 88
	this ->set_title( _("GParted") );
	this ->set_default_size( 775, 500 );
89
	
90 91
	try
	{
92
		this ->set_default_icon_name( "gparted" ) ;
93 94
	}
	catch ( Glib::Exception & e )
95
	{
96
		std::cout << e .what() << std::endl ;
97
	}
98 99 100

	// Pack the main box
	vbox_main.set_orientation(Gtk::ORIENTATION_VERTICAL);
101 102
	this ->add( vbox_main ); 
	
Bart Hakvoort's avatar
Bart Hakvoort committed
103
	//menubar....
104
	init_menubar() ;
Bart Hakvoort's avatar
Bart Hakvoort committed
105
	vbox_main .pack_start( menubar_main, Gtk::PACK_SHRINK );
106
	
Bart Hakvoort's avatar
Bart Hakvoort committed
107
	//toolbar....
108
	init_toolbar() ;
Bart Hakvoort's avatar
Bart Hakvoort committed
109
	vbox_main.pack_start( hbox_toolbar, Gtk::PACK_SHRINK );
110
	
111
	//drawingarea_visualdisk...  ( contains the visual represenation of the disks )
112
	drawingarea_visualdisk .signal_partition_selected .connect( 
113
			sigc::mem_fun( this, &Win_GParted::on_partition_selected ) ) ;
114
	drawingarea_visualdisk .signal_partition_activated .connect( 
115
			sigc::mem_fun( this, &Win_GParted::on_partition_activated ) ) ;
116
	drawingarea_visualdisk .signal_popup_menu .connect( 
117
			sigc::mem_fun( this, &Win_GParted::on_partition_popup_menu ) );
118
	vbox_main .pack_start( drawingarea_visualdisk, Gtk::PACK_SHRINK ) ;
119
	
Bart Hakvoort's avatar
Bart Hakvoort committed
120
	//hpaned_main (NOTE: added to vpaned_main)
121
	init_hpaned_main() ;
Luca Bacci's avatar
Luca Bacci committed
122
	vpaned_main.set_orientation(Gtk::ORIENTATION_VERTICAL);
Bart Hakvoort's avatar
Bart Hakvoort committed
123
	vpaned_main .pack1( hpaned_main, true, true ) ;
124
	
Bart Hakvoort's avatar
Bart Hakvoort committed
125
	//vpaned_main....
126
	vbox_main .pack_start( vpaned_main );
127
	
Bart Hakvoort's avatar
Bart Hakvoort committed
128
	//device info...
129
	init_device_info() ;
130
	
Bart Hakvoort's avatar
Bart Hakvoort committed
131
	//operationslist...
132 133 134 135
	hbox_operations .signal_undo .connect( sigc::mem_fun( this, &Win_GParted::activate_undo ) ) ;
	hbox_operations .signal_clear .connect( sigc::mem_fun( this, &Win_GParted::clear_operationslist ) ) ;
	hbox_operations .signal_apply .connect( sigc::mem_fun( this, &Win_GParted::activate_apply ) ) ;
	hbox_operations .signal_close .connect( sigc::mem_fun( this, &Win_GParted::close_operationslist ) ) ;
Bart Hakvoort's avatar
Bart Hakvoort committed
136
	vpaned_main .pack2( hbox_operations, true, true ) ;
137

138
	//statusbar... 
139
	pulsebar .set_pulse_step( 0.01 );
140 141 142
	pulsebar.set_valign(Gtk::ALIGN_CENTER);
	statusbar.pack_end(pulsebar, true, true, 10);
	statusbar.set_homogeneous();
143
	vbox_main .pack_start( statusbar, Gtk::PACK_SHRINK );
144
	
145
	this ->show_all_children();
146
	
147 148
	//make sure harddisk information is closed..
	hpaned_main .get_child1() ->hide() ;
149 150

	add_custom_css();
Bart Hakvoort's avatar
Bart Hakvoort committed
151 152
}

153 154 155 156 157 158
Win_GParted::~Win_GParted()
{
	delete copied_partition;
	copied_partition = NULL;
}

159
void Win_GParted::init_menubar() 
Bart Hakvoort's avatar
Bart Hakvoort committed
160
{
161 162
	Gtk::MenuItem *item;

163
	//fill menubar_main and connect callbacks 
Bart Hakvoort's avatar
Bart Hakvoort committed
164
	//gparted
165
	menu = manage( new Gtk::Menu() ) ;
Luca Bacci's avatar
Luca Bacci committed
166
	image = Utils::mk_image(Gtk::Stock::REFRESH, Gtk::ICON_SIZE_MENU);
167
	item = manage(new GParted::Menu_Helpers::ImageMenuElem(
168 169
		_("_Refresh Devices"),
		Gtk::AccelKey("<control>r"),
170
		*image, 
171 172
		sigc::mem_fun(*this, &Win_GParted::menu_gparted_refresh_devices)));
	menu->append(*item);
173
	
Luca Bacci's avatar
Luca Bacci committed
174
	image = Utils::mk_image(Gtk::Stock::HARDDISK, Gtk::ICON_SIZE_MENU);
175 176 177 178
	item = manage(new GParted::Menu_Helpers::ImageMenuElem(
		_("_Devices"), *image));
	menu->append(*item);
	mainmenu_items[MENU_DEVICES] = item;
179
	
180 181 182 183 184 185 186 187 188 189
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu->append(*item);

	item = manage(new GParted::Menu_Helpers::StockMenuElem(
		Gtk::Stock::QUIT, sigc::mem_fun(*this, &Win_GParted::menu_gparted_quit)));
	menu->append(*item);

	item = manage(new GParted::Menu_Helpers::MenuElem(
		_("_GParted"), *menu));
	menubar_main.append(*item);
190
	
191
	//edit
192
	menu = manage( new Gtk::Menu() ) ;
193
	item = manage(new GParted::Menu_Helpers::ImageMenuElem(
194
		_("_Undo Last Operation"), 
195
		Gtk::AccelKey("<control>z"),
Luca Bacci's avatar
Luca Bacci committed
196
		*Utils::mk_image(Gtk::Stock::UNDO, Gtk::ICON_SIZE_MENU),
197 198 199
		sigc::mem_fun(*this, &Win_GParted::activate_undo)));
	menu->append(*item);
	mainmenu_items[MENU_UNDO_OPERATION] = item;
200

201
	item = manage(new GParted::Menu_Helpers::ImageMenuElem(
202
		_("_Clear All Operations"), 
Luca Bacci's avatar
Luca Bacci committed
203
		*Utils::mk_image(Gtk::Stock::CLEAR, Gtk::ICON_SIZE_MENU),
204 205 206
		sigc::mem_fun(*this, &Win_GParted::clear_operationslist)));
	menu->append(*item);
	mainmenu_items[MENU_CLEAR_OPERATIONS] = item;
207

208
	item = manage(new GParted::Menu_Helpers::ImageMenuElem(
209
		_("_Apply All Operations"),
210
		Gtk::AccelKey(GDK_KEY_Return, Gdk::CONTROL_MASK),
Luca Bacci's avatar
Luca Bacci committed
211
		*Utils::mk_image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_MENU),
212 213 214 215 216 217 218 219
		sigc::mem_fun(*this, &Win_GParted::activate_apply)));
	menu->append(*item);
	mainmenu_items[MENU_APPLY_OPERATIONS] = item;

	item = manage(new GParted::Menu_Helpers::MenuElem(
		_("_Edit"), *menu));
	menubar_main.append(*item);
	mainmenu_items[MENU_EDIT] = item;
220

221
	//view
222
	menu = manage( new Gtk::Menu() ) ;
223

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
	item = manage(new GParted::Menu_Helpers::CheckMenuElem(
		_("Device _Information"), sigc::mem_fun(*this, &Win_GParted::menu_view_harddisk_info)));
	menu->append(*item);
	mainmenu_items[MENU_DEVICE_INFORMATION] = item;

	item = manage(new GParted::Menu_Helpers::CheckMenuElem(
		_("Pending _Operations"), sigc::mem_fun(*this, &Win_GParted::menu_view_operations)));
	menu->append(*item);
	mainmenu_items[MENU_PENDING_OPERATIONS] = item;

	item = manage(new GParted::Menu_Helpers::MenuElem(
		_("_View"), *menu));
	menubar_main.append(*item);

	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu->append(*item);

	item = manage( new GParted::Menu_Helpers::MenuElem(
		_("_File System Support"), sigc::mem_fun(*this, &Win_GParted::menu_gparted_features)));
	menu->append(*item);
	mainmenu_items[MENU_VIEW] = item;
245

246
	//device
247
	menu = manage( new Gtk::Menu() ) ;
248 249

	item = manage(new GParted::Menu_Helpers::MenuElem(
250
		Glib::ustring(_("_Create Partition Table") ) + "...",
251 252
		sigc::mem_fun(*this, &Win_GParted::activate_disklabel)));
	menu->append(*item);
253

254
	item = manage(new GParted::Menu_Helpers::MenuElem(
255
		Glib::ustring(_("_Attempt Data Rescue") ) + "...",
256 257
		sigc::mem_fun(*this, &Win_GParted::activate_attempt_rescue_data)));
	menu->append(*item);
258

259 260 261 262
	item = manage(new GParted::Menu_Helpers::MenuElem(
		_("_Device"), *menu));
	menubar_main.append(*item);
	mainmenu_items[MENU_DEVICE] = item;
263

264
	//partition
265
	init_partition_menu() ;
266 267 268 269 270

	item = manage(new GParted::Menu_Helpers::MenuElem(
		_("_Partition"), menu_partition));
	menubar_main.append(*item);
	mainmenu_items[MENU_PARTITION] = item;
271

Bart Hakvoort's avatar
Bart Hakvoort committed
272 273
	//help
	menu = manage( new Gtk::Menu() ) ;
274 275

	item = manage(new GParted::Menu_Helpers::ImageMenuElem(
276
		_("_Contents"), 
277
		Gtk::AccelKey("F1"),
Luca Bacci's avatar
Luca Bacci committed
278
		*Utils::mk_image(Gtk::Stock::HELP, Gtk::ICON_SIZE_MENU),
279 280
		sigc::mem_fun(*this, &Win_GParted::menu_help_contents)));
	menu->append(*item);
281

282 283 284 285 286 287 288 289 290 291
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu->append(*item);

	item = manage( new GParted::Menu_Helpers::StockMenuElem(
		Gtk::Stock::ABOUT, sigc::mem_fun(*this, &Win_GParted::menu_help_about)));
	menu->append(*item);

	item = manage(new GParted::Menu_Helpers::MenuElem(
		_("_Help"), *menu));
	menubar_main.append(*item);
Bart Hakvoort's avatar
Bart Hakvoort committed
292 293
}

294
void Win_GParted::init_toolbar() 
Bart Hakvoort's avatar
Bart Hakvoort committed
295
{
296
	int index = 0 ;
297 298
	// Initialize and pack toolbar_main
	hbox_toolbar.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
Bart Hakvoort's avatar
Bart Hakvoort committed
299
	hbox_toolbar.pack_start( toolbar_main );
300
	
Bart Hakvoort's avatar
Bart Hakvoort committed
301
	//NEW and DELETE
Luca Bacci's avatar
Luca Bacci committed
302
	image = Utils::mk_image(Gtk::Stock::NEW, Gtk::ICON_SIZE_BUTTON);
303 304 305
	/*TO TRANSLATORS: "New" is a tool bar item for partition actions. */
	Glib::ustring str_temp = _("New") ;
	toolbutton = Gtk::manage(new Gtk::ToolButton( *image, str_temp ));
306 307 308
	toolbutton ->signal_clicked() .connect( sigc::mem_fun( *this, &Win_GParted::activate_new ) );
	toolbar_main .append( *toolbutton );
	TOOLBAR_NEW = index++ ;
309
	toolbutton->set_tooltip_text(_("Create a new partition in the selected unallocated space"));
Luca Bacci's avatar
Luca Bacci committed
310 311 312 313
	image = Utils::mk_image(Gtk::Stock::DELETE, Gtk::ICON_SIZE_BUTTON);
	str_temp = Utils::get_stock_label(Gtk::Stock::DELETE);
	toolbutton = Gtk::manage(new Gtk::ToolButton(*image, str_temp));
	toolbutton->set_use_underline(true);
314 315
	toolbutton ->signal_clicked().connect( sigc::mem_fun(*this, &Win_GParted::activate_delete) );
	toolbar_main.append(*toolbutton);
316
	TOOLBAR_DEL = index++ ;
317
	toolbutton->set_tooltip_text(_("Delete the selected partition"));
Bart Hakvoort's avatar
Bart Hakvoort committed
318
	toolbar_main.append( *(Gtk::manage(new Gtk::SeparatorToolItem)) );
319
	index++ ;
320
	
Bart Hakvoort's avatar
Bart Hakvoort committed
321
	//RESIZE/MOVE
Luca Bacci's avatar
Luca Bacci committed
322
	image = Utils::mk_image(Gtk::Stock::GOTO_LAST, Gtk::ICON_SIZE_BUTTON);
323
	str_temp = _("Resize/Move") ;
324 325 326 327 328
	//Condition string split and Undo button.
	//  for longer translated string, split string in two and skip the Undo button to permit full toolbar to display
	//  FIXME:  Is there a better way to do this, perhaps without the conditional?  At the moment this seems to be the best compromise.
	bool display_undo = true ;
	if( str_temp .length() > 14 ) {
329 330 331 332 333
		size_t index = str_temp .find( "/" ) ;
		if ( index != Glib::ustring::npos ) {
			str_temp .replace( index, 1, "\n/" ) ;
			display_undo = false ;
		}
334 335
	}
	toolbutton = Gtk::manage(new Gtk::ToolButton( *image, str_temp ));
336 337
	toolbutton ->signal_clicked().connect( sigc::mem_fun(*this, &Win_GParted::activate_resize) );
	toolbar_main.append(*toolbutton);
338
	TOOLBAR_RESIZE_MOVE = index++ ;
339
	toolbutton->set_tooltip_text(_("Resize/Move the selected partition"));
Bart Hakvoort's avatar
Bart Hakvoort committed
340
	toolbar_main.append( *(Gtk::manage(new Gtk::SeparatorToolItem)) );
341 342
	index++ ;

Bart Hakvoort's avatar
Bart Hakvoort committed
343
	//COPY and PASTE
Luca Bacci's avatar
Luca Bacci committed
344 345 346 347
	image = Utils::mk_image(Gtk::Stock::COPY, Gtk::ICON_SIZE_BUTTON);
	str_temp = Utils::get_stock_label(Gtk::Stock::COPY);
	toolbutton = Gtk::manage(new Gtk::ToolButton(*image, str_temp));
	toolbutton->set_use_underline(true);
348 349
	toolbutton ->signal_clicked().connect( sigc::mem_fun(*this, &Win_GParted::activate_copy) );
	toolbar_main.append(*toolbutton);
350
	TOOLBAR_COPY = index++ ;
351
	toolbutton->set_tooltip_text(_("Copy the selected partition to the clipboard"));
Luca Bacci's avatar
Luca Bacci committed
352 353 354 355
	image = Utils::mk_image(Gtk::Stock::PASTE, Gtk::ICON_SIZE_BUTTON);
	str_temp = Utils::get_stock_label(Gtk::Stock::PASTE);
	toolbutton = Gtk::manage(new Gtk::ToolButton(*image, str_temp));
	toolbutton->set_use_underline(true);
356 357
	toolbutton ->signal_clicked().connect( sigc::mem_fun(*this, &Win_GParted::activate_paste) );
	toolbar_main.append(*toolbutton);
358
	TOOLBAR_PASTE = index++ ;
359
	toolbutton->set_tooltip_text(_("Paste the partition from the clipboard"));
Bart Hakvoort's avatar
Bart Hakvoort committed
360
	toolbar_main.append( *(Gtk::manage(new Gtk::SeparatorToolItem)) );
361
	index++ ;
362
	
Bart Hakvoort's avatar
Bart Hakvoort committed
363
	//UNDO and APPLY
364 365
	if ( display_undo ) {
		//Undo button is displayed only if translated language "Resize/Move" is not too long.  See above setting of this condition.
Luca Bacci's avatar
Luca Bacci committed
366 367 368 369
		image = Utils::mk_image(Gtk::Stock::UNDO, Gtk::ICON_SIZE_BUTTON);
		str_temp = Utils::get_stock_label(Gtk::Stock::UNDO);
		toolbutton = Gtk::manage(new Gtk::ToolButton(*image, str_temp));
		toolbutton->set_use_underline(true);
370 371 372 373
		toolbutton ->signal_clicked().connect( sigc::mem_fun(*this, &Win_GParted::activate_undo) );
		toolbar_main.append(*toolbutton);
		TOOLBAR_UNDO = index++ ;
		toolbutton ->set_sensitive( false );
374
		toolbutton->set_tooltip_text(_("Undo Last Operation"));
375
	}
Luca Bacci's avatar
Luca Bacci committed
376 377 378 379 380

	image = Utils::mk_image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_BUTTON);
	str_temp = Utils::get_stock_label(Gtk::Stock::APPLY);
	toolbutton = Gtk::manage(new Gtk::ToolButton(*image, str_temp));
	toolbutton->set_use_underline(true);
381 382
	toolbutton ->signal_clicked().connect( sigc::mem_fun(*this, &Win_GParted::activate_apply) );
	toolbar_main.append(*toolbutton);
383
	TOOLBAR_APPLY = index++ ;
384
	toolbutton ->set_sensitive( false );
385 386
	toolbutton->set_tooltip_text(_("Apply All Operations"));

387 388 389 390
	//initialize and pack combo_devices
	liststore_devices = Gtk::ListStore::create( treeview_devices_columns ) ;
	combo_devices .set_model( liststore_devices ) ;

391
	combo_devices .pack_start( treeview_devices_columns .icon, false ) ;
392
	combo_devices .pack_start( treeview_devices_columns .device ) ;
393
	combo_devices .pack_start( treeview_devices_columns .size, false ) ;
394
	
395 396
	combo_devices_changed_connection =
		combo_devices .signal_changed() .connect( sigc::mem_fun(*this, &Win_GParted::combo_devices_changed) );
397 398

	hbox_toolbar .pack_start( combo_devices, Gtk::PACK_SHRINK ) ;
Bart Hakvoort's avatar
Bart Hakvoort committed
399 400
}

401
void Win_GParted::init_partition_menu() 
Bart Hakvoort's avatar
Bart Hakvoort committed
402
{
403
	Gtk::MenuItem *item;
404

405
	//fill menu_partition
Luca Bacci's avatar
Luca Bacci committed
406
	image = Utils::mk_image(Gtk::Stock::NEW, Gtk::ICON_SIZE_MENU);
407
	item = manage(new
408
			/*TO TRANSLATORS: "_New" is a sub menu item for the partition menu. */
409
			GParted::Menu_Helpers::ImageMenuElem(_("_New"),
410
							  Gtk::AccelKey(GDK_KEY_Insert, Gdk::BUTTON1_MASK),
411
							  *image,
412 413 414
							  sigc::mem_fun(*this, &Win_GParted::activate_new)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_NEW] = item;
415

416
	item = manage(new
417
			GParted::Menu_Helpers::StockMenuElem(Gtk::Stock::DELETE,
418
							  Gtk::AccelKey(GDK_KEY_Delete, Gdk::BUTTON1_MASK),
419 420 421
							  sigc::mem_fun(*this, &Win_GParted::activate_delete)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_DEL] = item;
422

423 424
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu_partition.append(*item);
Luca Bacci's avatar
Luca Bacci committed
425 426

	image = Utils::mk_image(Gtk::Stock::GOTO_LAST, Gtk::ICON_SIZE_MENU);
427
	item = manage(new
428
			GParted::Menu_Helpers::ImageMenuElem(_("_Resize/Move"),
429
							  *image, 
430 431 432
							  sigc::mem_fun(*this, &Win_GParted::activate_resize)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_RESIZE_MOVE] = item;
433
	
434 435
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu_partition.append(*item);
436
	
437
	item = manage(new
438
			GParted::Menu_Helpers::StockMenuElem(Gtk::Stock::COPY,
439 440 441
							  sigc::mem_fun(*this, &Win_GParted::activate_copy)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_COPY] = item;
442
	
443
	item = manage(new
444
			GParted::Menu_Helpers::StockMenuElem(Gtk::Stock::PASTE,
445 446 447
							  sigc::mem_fun(*this, &Win_GParted::activate_paste)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_PASTE] = item;
448
	
449 450
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu_partition.append(*item);
Luca Bacci's avatar
Luca Bacci committed
451 452

	image = Utils::mk_image(Gtk::Stock::CONVERT, Gtk::ICON_SIZE_MENU);
453
	item = manage(new
Piotr Drąg's avatar
Piotr Drąg committed
454
			/*TO TRANSLATORS: menuitem which holds a submenu with file systems.. */
455
			GParted::Menu_Helpers::ImageMenuElem(_("_Format to"),
456
							  *image,
457 458 459
							  *create_format_menu()));
	menu_partition.append(*item);
	partitionmenu_items[MENU_FORMAT] = item;
460
	
461 462
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu_partition.append(*item);
463

464
	item = manage(new
465
			// Placeholder text, replaced in set_valid_operations() before the menu is shown
466
			GParted::Menu_Helpers::MenuElem("--toggle crypt busy--",
467 468 469
			                             sigc::mem_fun(*this, &Win_GParted::toggle_crypt_busy_state)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_TOGGLE_CRYPT_BUSY] = item;
470

471
	item = manage(new
472
			// Placeholder text, replaced in set_valid_operations() before the menu is shown
473
			GParted::Menu_Helpers::MenuElem("--toggle fs busy--",
474 475 476
						     sigc::mem_fun(*this, &Win_GParted::toggle_fs_busy_state)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_TOGGLE_FS_BUSY] = item;
477

478
	item = manage(new
Piotr Drąg's avatar
Piotr Drąg committed
479
			/*TO TRANSLATORS: menuitem which holds a submenu with mount points.. */
480 481 482
			GParted::Menu_Helpers::MenuElem(_("_Mount on"), *manage(new Gtk::Menu())));
	menu_partition.append(*item);
	partitionmenu_items[MENU_MOUNT] = item;
483

484 485
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu_partition.append(*item);
486

487
	item = manage(new
488
			GParted::Menu_Helpers::MenuElem(_("_Name Partition"),
489 490 491
			                             sigc::mem_fun(*this, &Win_GParted::activate_name_partition)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_NAME_PARTITION] = item;
492

493
	item = manage(new
494
			GParted::Menu_Helpers::MenuElem(_("M_anage Flags"),
495 496 497
						     sigc::mem_fun(*this, &Win_GParted::activate_manage_flags)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_FLAGS] = item;
498

499
	item = manage(new
500
			GParted::Menu_Helpers::MenuElem(_("C_heck"),
501 502 503
						     sigc::mem_fun(*this, &Win_GParted::activate_check)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_CHECK] = item;
504

505
	item = manage(new
506
			GParted::Menu_Helpers::MenuElem(_("_Label File System"),
507 508 509
			                             sigc::mem_fun(*this, &Win_GParted::activate_label_filesystem)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_LABEL_PARTITION] = item;
510

511
	item = manage(new
512
			GParted::Menu_Helpers::MenuElem(_("New UU_ID"),
513 514 515
						     sigc::mem_fun(*this, &Win_GParted::activate_change_uuid)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_CHANGE_UUID] = item;
516

517 518 519 520
	item = manage(new GParted::Menu_Helpers::SeparatorElem());
	menu_partition.append(*item);

	item = manage(new
521
			GParted::Menu_Helpers::StockMenuElem(Gtk::Stock::DIALOG_INFO,
522 523 524
							  sigc::mem_fun(*this, &Win_GParted::activate_info)));
	menu_partition.append(*item);
	partitionmenu_items[MENU_INFO] = item;
525 526
	
	menu_partition .accelerate( *this ) ;  
Bart Hakvoort's avatar
Bart Hakvoort committed
527 528
}

529
//Create the Partition --> Format to --> (file system list) menu
530
Gtk::Menu * Win_GParted::create_format_menu()
Bart Hakvoort's avatar
Bart Hakvoort committed
531
{
532
	const std::vector<FS> & fss = gparted_core .get_filesystems() ;
533 534
	menu = manage( new Gtk::Menu() ) ;

535
	for ( unsigned int t = 0 ; t < fss .size() ; t++ )
Bart Hakvoort's avatar
Bart Hakvoort committed
536
	{
537 538
		if ( GParted_Core::supported_filesystem( fss[t].filesystem ) &&
		     fss[t].filesystem != FS_LUKS                               )
539
			create_format_menu_add_item( fss[t].filesystem, fss[t].create );
Bart Hakvoort's avatar
Bart Hakvoort committed
540
	}
541 542
	//Add cleared at the end of the list
	create_format_menu_add_item( FS_CLEARED, true ) ;
543

544
	return menu ;
Bart Hakvoort's avatar
Bart Hakvoort committed
545
}
546 547

//Add one entry to the Partition --> Format to --> (file system list) menu
548
void Win_GParted::create_format_menu_add_item( FSType filesystem, bool activate )
549
{
550
	hbox = manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
551 552 553 554 555 556 557
	//the colored square
	hbox ->pack_start( * manage( new Gtk::Image( Utils::get_color_as_pixbuf( filesystem, 16, 16 ) ) ),
	                   Gtk::PACK_SHRINK ) ;
	//the label...
	hbox ->pack_start( * Utils::mk_label( " " + Utils::get_filesystem_string( filesystem ) ),
	                   Gtk::PACK_SHRINK ) ;

558 559
	Gtk::MenuItem *item = manage(new Gtk::MenuItem(*hbox));
	menu->append(*item);
560
	if ( activate )
561
		item->signal_activate().connect(
562
			sigc::bind<FSType>( sigc::mem_fun( *this, &Win_GParted::activate_format ), filesystem ) );
563
	else
564
		item->set_sensitive(false);
565 566
}

Bart Hakvoort's avatar
Bart Hakvoort committed
567 568
void Win_GParted::init_device_info()
{
569
	vbox_info.set_orientation(Gtk::ORIENTATION_VERTICAL);
570
	vbox_info.set_spacing( 5 );
571 572
	int top = 0;

573
	//title
574
	vbox_info .pack_start( 
575
		* Utils::mk_label( " <b>" + static_cast<Glib::ustring>( _("Device Information") ) + "</b>" ),
Bart Hakvoort's avatar
Bart Hakvoort committed
576
		Gtk::PACK_SHRINK );
577

578
	//GENERAL DEVICE INFO
579 580 581 582 583 584
	Gtk::Grid *grid = manage(new Gtk::Grid());
	grid->set_column_spacing(10);

	// Model
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Model:")) + "</b>"),
	             0, top, 1, 1);
585
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
586
	grid->attach(*device_info.back(), 1, top++, 1, 1);
587 588

	// Serial number
589 590
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Serial:")) + "</b>"),
	             0, top, 1, 1);
591
	device_info.push_back( Utils::mk_label( "", true, false, true ) );
592
	grid->attach(*device_info.back(), 1, top++, 1, 1);
593

594 595 596
	// Size
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Size:")) + "</b>"),
	             0, top, 1, 1);
597
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
598 599 600 601 602
	grid->attach(*device_info.back(), 1, top++, 1, 1);

	// Path
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Path:")) + "</b>"),
	             0, top, 1, 1);
603
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
	grid->attach(*device_info.back(), 1, top++, 1, 1);

	vbox_info.pack_start(*grid, Gtk::PACK_SHRINK);

	//DETAILED DEVICE INFO
	top = 0;
	grid = manage(new Gtk::Grid());
	grid->set_column_spacing(10);

	// One blank line
	grid->attach(*Utils::mk_label(""), 1, top++, 1, 1);

	// Disktype
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Partition table:")) + "</b>"),
	             0, top, 1, 1);
619
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
620 621 622 623 624
	grid->attach(*device_info.back(), 1, top++, 1, 1);

	// Heads
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Heads:")) + "</b>"),
	             0, top, 1, 1);
625
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
626 627 628 629 630
	grid->attach(*device_info.back(), 1, top++, 1, 1);

	// Sectors / track
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Sectors/track:")) + "</b>"),
	             0, top, 1, 1);
631
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
632 633 634 635 636
	grid->attach(*device_info.back(), 1, top++, 1, 1);

	// Cylinders
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Cylinders:")) + "</b>"),
	             0, top, 1, 1);
637
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
638 639 640 641 642
	grid->attach(*device_info.back(), 1, top++, 1, 1);

	// Total sectors
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Total sectors:")) + "</b>"),
	             0, top, 1, 1);
643
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
644
	grid->attach(*device_info.back(), 1, top++, 1, 1);
645

646 647 648
	// Sector size
	grid->attach(*Utils::mk_label(" <b>" + static_cast<Glib::ustring>(_("Sector size:")) + "</b>"),
	             0, top, 1, 1);
649
	device_info .push_back( Utils::mk_label( "", true, false, true ) ) ;
650
	grid->attach(*device_info.back(), 1, top++, 1, 1);
651

652
	vbox_info.pack_start(*grid, Gtk::PACK_SHRINK);
Bart Hakvoort's avatar
Bart Hakvoort committed
653 654
}

655
void Win_GParted::init_hpaned_main() 
Bart Hakvoort's avatar
Bart Hakvoort committed
656
{
Luca Bacci's avatar
Luca Bacci committed
657
	hpaned_main.set_orientation(Gtk::ORIENTATION_HORIZONTAL);
Bart Hakvoort's avatar
Bart Hakvoort committed
658
	//left scrollwindow (holds device info)
659
	scrollwindow = manage( new Gtk::ScrolledWindow() ) ;
660 661
	scrollwindow ->set_shadow_type( Gtk::SHADOW_ETCHED_IN );
	scrollwindow ->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
662 663 664
#if HAVE_SET_PROPAGATE_NATURAL_WIDTH
	scrollwindow->set_propagate_natural_width(true);
#endif
Bart Hakvoort's avatar
Bart Hakvoort committed
665

666
	hpaned_main .pack1( *scrollwindow, true, true );
Bart Hakvoort's avatar
Bart Hakvoort committed
667 668 669
	scrollwindow ->add( vbox_info );

	//right scrollwindow (holds treeview with partitions)
670
	scrollwindow = manage( new Gtk::ScrolledWindow() ) ;
671 672
	scrollwindow ->set_shadow_type( Gtk::SHADOW_ETCHED_IN );
	scrollwindow ->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
673 674 675 676
#if HAVE_SET_PROPAGATE_NATURAL_WIDTH
	scrollwindow->set_propagate_natural_width(true);
#endif

677 678 679 680
	//connect signals and add treeview_detail
	treeview_detail .signal_partition_selected .connect( sigc::mem_fun( this, &Win_GParted::on_partition_selected ) );
	treeview_detail .signal_partition_activated .connect( sigc::mem_fun( this, &Win_GParted::on_partition_activated ) );
	treeview_detail .signal_popup_menu .connect( sigc::mem_fun( this, &Win_GParted::on_partition_popup_menu ) );
681
	scrollwindow ->add( treeview_detail );
682
	hpaned_main .pack2( *scrollwindow, true, true );
Bart Hakvoort's avatar
Bart Hakvoort committed
683 684
}

685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
void Win_GParted::add_custom_css()
{
	Glib::RefPtr<Gdk::Screen> default_screen = Gdk::Screen::get_default();
	Glib::RefPtr<Gtk::CssProvider> provider = Gtk::CssProvider::create();

	Glib::ustring custom_css;
	if (gtk_get_minor_version() >= 20)
		custom_css = "progressbar progress, trough { min-height: 8px; }";
	else
		custom_css = "GtkProgressBar { -GtkProgressBar-min-horizontal-bar-height: 8px; }";

	try
	{
		provider->load_from_data(custom_css);
	}
	catch (Glib::Error& e)
	{
		std::cerr << e.what() << std::endl;
	}

	Gtk::StyleContext::add_provider_for_screen(default_screen,
	                                           provider,
	                                           GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}

710
void Win_GParted::refresh_combo_devices()
711
{
712 713 714 715
	// Temporarily block the on change callback while re-creating the device list
	// behind the combobox to prevent flashing redraw by being redrawn with an empty
	// device list.
	combo_devices_changed_connection .block();
716
	liststore_devices ->clear() ;
717
	
718 719
	menu = manage( new Gtk::Menu() ) ;
	Gtk::RadioButtonGroup radio_group ;
720
	
721
	for ( unsigned int i = 0 ; i < devices .size( ) ; i++ )
722 723
	{
		//combo...
724 725
		treerow = *( liststore_devices ->append() ) ;
		treerow[ treeview_devices_columns .icon ] =
Luca Bacci's avatar
Luca Bacci committed
726
			Utils::mk_pixbuf(*this, Gtk::Stock::HARDDISK, Gtk::ICON_SIZE_LARGE_TOOLBAR);
727
		treerow[ treeview_devices_columns .device ] = devices[ i ] .get_path() ;
728
		treerow[ treeview_devices_columns .size ] = "(" + Utils::format_size( devices[ i ] .length, devices[ i ] .sector_size ) + ")" ; 
729 730 731

		// Devices submenu...
		hbox = manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
732
		hbox ->pack_start( * Utils::mk_label( devices[ i ] .get_path() ), Gtk::PACK_EXPAND_WIDGET ) ;
733
		hbox ->pack_start( * Utils::mk_label( "   (" + Utils::format_size( devices[ i ] .length, devices[ i ] .sector_size ) + ")" ),
734 735
		                   Gtk::PACK_SHRINK ) ;

736 737 738 739
		Gtk::RadioMenuItem *item = manage(new Gtk::RadioMenuItem(radio_group));
		menu->append(*item);
		item->add(*hbox);
		item->signal_activate().connect(
740
			sigc::bind<unsigned int>( sigc::mem_fun(*this, &Win_GParted::radio_devices_changed), i ) ) ;
Bart Hakvoort's avatar
Bart Hakvoort committed
741
	}
742

743
	mainmenu_items[MENU_DEVICES]->unset_submenu();
744

745
	if (menu->get_children().size())
746 747
	{
		menu ->show_all() ;
748
		mainmenu_items[MENU_DEVICES]->set_submenu(*menu);
749
	}
750 751

	combo_devices_changed_connection .unblock();
752
	combo_devices .set_active( current_device ) ;
753 754
}

755 756 757 758 759 760 761 762 763 764 765 766
bool Win_GParted::pulsebar_pulse()
{
	pulsebar.pulse();
	Glib::ustring tmp_msg = gparted_core .get_thread_status_message() ;
	if ( tmp_msg != "" ) {
		statusbar.pop();
		statusbar.push( tmp_msg );
	}

	return true;
}

767
void Win_GParted::show_pulsebar( const Glib::ustring & status_message ) 
768
{
769
	pulsebar .show();
770
	statusbar .push( status_message) ;
771
	
772 773 774
	//disable all input stuff
	toolbar_main .set_sensitive( false ) ;
	menubar_main .set_sensitive( false ) ;
775
	combo_devices .set_sensitive( false ) ;
776
	menu_partition .set_sensitive( false ) ;
777
	treeview_detail .set_sensitive( false ) ;
778
	drawingarea_visualdisk .set_sensitive( false ) ;
779
		
780 781
	// connect pulse update timer
	pulsetimer = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Win_GParted::pulsebar_pulse), 100 );
782 783 784 785
}

void Win_GParted::hide_pulsebar()
{
786
	pulsetimer.disconnect();
787
	pulsebar .hide();
788
	statusbar .pop() ;
789
		
790 791 792
	//enable all disabled stuff
	toolbar_main .set_sensitive( true ) ;
	menubar_main .set_sensitive( true ) ;
793
	combo_devices .set_sensitive( true ) ;
794
	menu_partition .set_sensitive( true ) ;
795
	treeview_detail .set_sensitive( true ) ;
796
	drawingarea_visualdisk .set_sensitive( true ) ;
Bart Hakvoort's avatar
Bart Hakvoort committed
797 798
}

799
void Win_GParted::Fill_Label_Device_Info( bool clear ) 
Bart Hakvoort's avatar
Bart Hakvoort committed
800
{
801 802 803
	if ( clear )
		for ( unsigned int t = 0 ; t < device_info .size( ) ; t++ )
			device_info[ t ] ->set_text( "" ) ;
804
		
805
	else
806
	{		
807
		short t = 0;
808
		
809 810
		//global info...
		device_info[ t++ ] ->set_text( devices[ current_device ] .model ) ;
811
		device_info[ t++ ] ->set_text( devices[current_device].serial_number );
812
		device_info[ t++ ] ->set_text( Utils::format_size( devices[ current_device ] .length, devices[ current_device ] .sector_size ) ) ;
813 814
		device_info[ t++ ] ->set_text( devices[current_device].get_path() );

815 816
		//detailed info
		device_info[ t++ ] ->set_text( devices[ current_device ] .disktype ) ;
817 818 819 820
		device_info[ t++ ] ->set_text( Utils::num_to_str( devices[ current_device ] .heads ) );
		device_info[ t++ ] ->set_text( Utils::num_to_str( devices[ current_device ] .sectors ) );
		device_info[ t++ ] ->set_text( Utils::num_to_str( devices[ current_device ] .cylinders ) );
		device_info[ t++ ] ->set_text( Utils::num_to_str( devices[ current_device ] .length ) );
821
		device_info[ t++ ] ->set_text( Utils::num_to_str( devices[ current_device ] .sector_size ) );
822
	}
Bart Hakvoort's avatar
Bart Hakvoort committed
823 824
}

825
bool Win_GParted::on_delete_event( GdkEventAny *event )
Bart Hakvoort's avatar
Bart Hakvoort committed
826
{
827
	return ! Quit_Check_Operations();
828
}	
Bart Hakvoort's avatar
Bart Hakvoort committed
829

830
void Win_GParted::Add_Operation( const Device & device, Operation * operation )
Bart Hakvoort's avatar
Bart Hakvoort committed
831
{
832
	if ( operation )
833
	{ 
834
		Glib::ustring error ;
835 836 837
		//Add any of the listed operations without further checking, but
		//  for the other operations (_CREATE, _RESIZE_MOVE and _COPY)
		//  ensure the partition is correctly aligned.
838
		//FIXME: this is becoming a mess.. maybe it's better to check if partition_new > 0
839 840
		if ( operation ->type == OPERATION_DELETE ||
		     operation ->type == OPERATION_FORMAT ||
841
		     operation ->type == OPERATION_CHECK ||
842
		     operation ->type == OPERATION_CHANGE_UUID ||
843
		     operation ->type == OPERATION_LABEL_FILESYSTEM ||
844
		     operation ->type == OPERATION_NAME_PARTITION ||
845
		     gparted_core.valid_partition(device, operation->get_partition_new(), error)
846
		   )
847 848
		{
			operation ->create_description() ;
849
			operations.push_back( operation );
850
		}
851
		else
852 853
		{
			Gtk::MessageDialog dialog( *this,
854
				   _("Could not add this operation to the list"),
855 856 857 858 859
				   false,
				   Gtk::MESSAGE_ERROR,
				   Gtk::BUTTONS_OK,
				   true );
			dialog .set_secondary_text( error ) ;
860

861 862
			dialog .run() ;
		}
863
	}
Bart Hakvoort's avatar
Bart Hakvoort committed
864 865
}

866
// Try to merge the second operation into the first in the operations[] vector.
867
bool Win_GParted::merge_two_operations( unsigned int first, unsigned int second )
868
{
869 870 871 872
	unsigned int num_ops = operations.size();
	if ( first >= num_ops-1 )
		return false;
	if ( first >= second || second >= num_ops )
873 874
		return false;

875
	if ( operations[first]->merge_operations( *operations[second] ) )
876 877 878 879 880 881 882 883
	{
		remove_operation( second );
		return true;
	}

	return false;
}

884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907
// Try to merge pending operations in the operations[] vector using the specified merge
// type.
//
// Summary of all the operation merging rules for each operation type coded into the
// ::activate_*() methods:
//
// Operation type      Partition status    Merge type             Method
// -----------------   ----------------    --------------------   -----------------
// resize/move         Real                MERGE_LAST_WITH_PREV   activate_resize()
// resize/move         New                 MERGE_LAST_WITH_ANY    activate_resize()
// paste               *                   none                   activate_paste()
// new                 *                   none                   activate_new()
// delete              Real                none                   activate_delete()
// delete              New                 MERGE_ALL_ADJACENT     activate_delete()
// format              Real                MERGE_LAST_WITH_PREV   activate_format()
// format              New                 MERGE_LAST_WITH_ANY    activate_format()
// check               Real [1]            MERGE_LAST_WITH_ANY    activate_check()
// label file system   Real [1]            MERGE_LAST_WITH_ANY    activate_label_filesystem()
// name partition      Real [1]            MERGE_LAST_WITH_ANY    activate_name_partition()
// new UUID            Real [1]            MERGE_LAST_WITH_ANY    activate_change_uuid()
//
// [1] The UI only allows these operations to be applied to real partitions; where as the
//     other mergeable operations can be applied to both real partitions and new, pending
//     create partitions.
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939
void Win_GParted::merge_operations( MergeType mergetype )
{
	unsigned int num_ops = operations.size();
	if ( num_ops <= 1 )
		return;  // Nothing to merge.  One or fewer operations.

	switch ( mergetype )
	{
		case MERGE_LAST_WITH_PREV:
			merge_two_operations( num_ops-2, num_ops-1 );
			break;

		case MERGE_LAST_WITH_ANY:
			for ( unsigned int i = 0 ; i < num_ops-1 ; i ++ )
			{
				if ( merge_two_operations( i, num_ops-1 ) )
					break;
			}
			break;

		case MERGE_ALL_ADJACENT:
			// Must check against operations.size() as looping continues after
			// merging which might have reduced the number of items in the
			// vector.
			for ( unsigned int i = 0 ; i < operations.size()-1 ; i ++ )
			{
				merge_two_operations( i, i+1 );
			}
			break;
	}
}

940
void Win_GParted::Refresh_Visual()
Bart Hakvoort's avatar
Bart Hakvoort committed
941
{
942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959
	// How GParted displays partitions in the GUI and manages the lifetime and
	// ownership of that data:
	//
	// (1) Queries the devices and partitions on disk and refreshes the model.
	//
	//     Data owner: std::vector<Devices> Win_GParted::devices
	//     Lifetime:   Valid until the next call to Refresh_Visual()
	//     Call chain:
	//
	//         Win_GParted::menu_gparted_refresh_devices()
	//             gparted_core.set_devices( devices )
	//                 GParted_Core::set_devices_thread( devices )
	//                     devices.clear()
	//                     etc.
	//
	// (2) Takes a copy of the partitions for the device currently being shown in the
	//     GUI and visually applies pending operations.
	//
960
	//     Data owner: PartitionVector Win_GParted::display_partitions
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011