5 const string log_domain
= "Gmpc.DataView";
7 /** The Default column width. */
8 const int default_column_width
= 200;
12 * * List of column ids to show.
13 * * Name of each column
14 * * Default set of enabled columns.
16 const int NUM_COLS
= 20;
17 const int[] gmpc_data_view_col_ids
= {
18 Gmpc
.MpdData
.ColumnTypes
.MARKUP
,
19 Gmpc
.MpdData
.ColumnTypes
.SONG_ARTIST
, /* album name */
20 Gmpc
.MpdData
.ColumnTypes
.SONG_ALBUM
, /* album name */
21 Gmpc
.MpdData
.ColumnTypes
.SONG_TITLE
, /* song title */
22 Gmpc
.MpdData
.ColumnTypes
.SONG_TITLEFILE
, /* song title */
23 Gmpc
.MpdData
.ColumnTypes
.SONG_GENRE
, /* song genre */
24 Gmpc
.MpdData
.ColumnTypes
.SONG_TRACK
, /* song track */
25 Gmpc
.MpdData
.ColumnTypes
.SONG_NAME
, /* stream name */
26 Gmpc
.MpdData
.ColumnTypes
.SONG_COMPOSER
, /* composer name */
27 Gmpc
.MpdData
.ColumnTypes
.SONG_PERFORMER
, /* performer */
28 Gmpc
.MpdData
.ColumnTypes
.SONG_DATE
, /* date */
29 Gmpc
.MpdData
.ColumnTypes
.SONG_LENGTH_FORMAT
, /* length formatted */
30 Gmpc
.MpdData
.ColumnTypes
.SONG_DISC
, /* disc */
31 Gmpc
.MpdData
.ColumnTypes
.SONG_COMMENT
, /* comment */
32 Gmpc
.MpdData
.ColumnTypes
.ICON_ID
, /* icon id */
33 Gmpc
.MpdData
.ColumnTypes
.SONG_POS
,
34 Gmpc
.MpdData
.ColumnTypes
.SONG_ALBUMARTIST
,
35 Gmpc
.MpdData
.ColumnTypes
.PATH_EXTENSION
, /* Extension */
36 Gmpc
.MpdData
.ColumnTypes
.PATH_DIRECTORY
, /* Directory */
37 Gmpc
.MpdData
.ColumnTypes
.SONG_PRIORITY
39 const string[] gmpc_data_view_col_names
= {
62 const bool[] gmpc_data_view_col_enabled
= {
86 const int[] gmpc_data_view_col_position
= {
109 public class Gmpc
.DataView
: Gtk
.TreeView
111 private Gtk
.TreeViewColumn
[] tree_columns
= new Gtk
.TreeViewColumn
[NUM_COLS
];
113 * If we are a play-queue we should treat the content.
114 * slightly different.
115 * e.g. add-replace will be play-crop
117 public bool is_play_queue
{get; set; default=false;}
120 * The name of the treeview.
121 * This is used to store the column layout.
123 public string uid
{get; set; default="default";}
127 * Construction function.
129 public DataView(string name
)
131 log(log_domain
, LogLevelFlags
.LEVEL_INFO
, "Constructing dataview: "+name
);
134 // Connect row activated signal.
135 this
.row_activated
.connect(__row_activated
);
136 this
.key_release_event
.connect(__key_release_event_callback
);
137 // When it getst he destroy signal.
138 this
.destroy
.connect(store_columns
);
140 this
.set_rules_hint(true);
142 this
.get_selection().set_mode(Gtk
.SelectionMode
.MULTIPLE
);
143 this
.set_fixed_height_mode(true);
149 * Store the position, visibility and width of the columns
151 private void store_columns()
153 // Save the position of the columns
154 var columns
= get_columns();
156 foreach(var column
in columns
)
158 int id
= column
.get_data("id");
159 int width
= column
.get_width();
160 config
.set_int(uid
+"-colpos", gmpc_data_view_col_names
[id
], index
);
161 config
.set_bool(uid
+"-colshow", gmpc_data_view_col_names
[id
], column
.visible
);
162 // Only store width if bigger then 0.
164 config
.set_int(uid
+"-colsize",gmpc_data_view_col_names
[id
], width
);
179 * Populate the treeview with the right columns.
180 * The treeview should have a name now.
182 private void populate()
184 for(int i
= 0; i
< NUM_COLS
; i
++)
186 Gtk
.TreeViewColumn col
= new Gtk
.TreeViewColumn();
187 col
.set_data("id", i
);
188 if(gmpc_data_view_col_ids
[i
] == Gmpc
.MpdData
.ColumnTypes
.ICON_ID
)
193 var renderer
= new Gtk
.CellRendererPixbuf();
194 renderer
.xalign
= 0.0f
;
196 col
.pack_start(renderer
, true);
197 col
.set_attributes(renderer
, "icon-name", Gmpc
.MpdData
.ColumnTypes
.ICON_ID
);
198 col
.set_resizable(false);
199 col
.set_fixed_width(20);
204 col
.set_title(gmpc_data_view_col_names
[i
]);
205 var renderer
= new Gtk
.CellRendererText();
206 renderer
.ellipsize
= Pango
.EllipsizeMode
.END
;
207 renderer
.weight_set
= true;
209 col
.pack_start(renderer
, true);
210 col
.set_attributes(renderer
, "text", gmpc_data_view_col_ids
[i
]);
211 col
.set_resizable(true);
214 // col.set_cell_data_func(renderer, (Gtk.CellLayoutDataFunc)highlight_row_current_song_playing);
217 int width
= config
.get_int_with_default(uid
+"-colsize",gmpc_data_view_col_names
[i
], default_column_width
);
218 // Do not set to size 0, then revert back to 200.
219 col
.set_fixed_width(width
>0?width
:default_column_width
);
221 col
.set_sizing(Gtk
.TreeViewColumnSizing
.FIXED
);
222 col
.set_reorderable(true);
225 int pos
= config
.get_int_with_default(uid
+"-colpos", gmpc_data_view_col_names
[i
], gmpc_data_view_col_position
[i
]);
226 this
.tree_columns
[pos
] = col
;
228 // Add the columns (in right order)
229 for(int i
= 0; i
< NUM_COLS
; i
++) {
230 int id
= this
.tree_columns
[i
].get_data("id");
231 this
.insert_column(this
.tree_columns
[i
], i
);
232 this
.tree_columns
[i
].set_visible(config
.get_bool_with_default(uid
+"-colshow", gmpc_data_view_col_names
[id
], gmpc_data_view_col_enabled
[id
]));
239 * Internal functions.
243 * Function handles the row-activate signal.
245 private void __row_activated (Gtk
.TreePath path
, Gtk
.TreeViewColumn col
)
247 Gtk
.TreeModel? model
= this
.get_model();
251 if(!model
.get_iter(out iter
, path
)) return;
253 /* If we are play-queue, play the selected song. */
255 model
.get(iter
, Gmpc
.MpdData
.ColumnTypes
.SONG_ID
, out song_id
);
256 MPD
.Player
.play_id(Gmpc
.server
, song_id
);
258 /* If we are a song browser, add the path and play it. */
260 model
.get(iter
, Gmpc
.MpdData
.ColumnTypes
.PATH
, out song_path
);
261 MpdInteraction
.play_path(song_path
);
266 * Check if current row is playing.
269 private void highlight_row_current_song_playing(Gtk
.TreeViewColumn col
, Gtk
.CellRenderer renderer
, Gtk
.TreeModel model
, Gtk
.TreeIter iter
)
271 (renderer as Gtk
.CellRendererText
).weight
= Pango
.Weight
.BOLD
;
276 * Handle keyboard input.
278 private bool __key_release_event_callback(Gdk
.EventKey event
)
280 if(event
.keyval
== Gdk
.Key_y
)
282 // Copy data to clipboard
285 else if (event
.keyval
== Gdk
.Key_c
)
287 // Cut (if available) into clipboard
289 else if (event
.keyval
== Gdk
.Key_P
)
293 else if (event
.keyval
== Gdk
.Key_p
)
297 else if (event
.keyval
== Gdk
.Key_Escape
)
302 // Commands specific to play_queue
305 if (event
.keyval
== Gdk
.Key_Q
)
308 return selected_songs_remove_priority();
310 else if (event
.keyval
== Gdk
.Key_q
)
313 return selected_songs_raise_priority();
315 else if (event
.keyval
== Gdk
.Key_d
)
317 return selected_songs_remove();
322 if(event
.keyval
== Gdk
.Key_i
)
331 * Interaction on selected songs.
333 // Set priority on the selected songs.
334 private bool selected_songs_raise_priority()
336 if(server
.check_command_allowed("prioid") != MPD
.Server
.Command
.ALLOWED
) return false;
337 var selection
= this
.get_selection();
339 if(selection
.count_selected_rows() > 254) {
340 Gmpc
.Messages
.show(_("You can only queue 254 songs at the time."), Gmpc
.Messages
.Level
.WARNING
);
346 foreach(var path
in selection
.get_selected_rows(out model
))
349 if(model
.get_iter(out iter
, path
))
352 model
.get(iter
,Gmpc
.MpdData
.ColumnTypes
.SONG_ID
, out song_id
);
353 MPD
.PlayQueue
.set_priority(server
, song_id
, priority
--);
358 // Remove the set priority from the selected songs.
359 private bool selected_songs_remove_priority()
361 if(server
.check_command_allowed("prioid") != MPD
.Server
.Command
.ALLOWED
) return false;
362 var selection
= this
.get_selection();
365 foreach(var path
in selection
.get_selected_rows(out model
))
368 if(model
.get_iter(out iter
, path
))
371 model
.get(iter
,Gmpc
.MpdData
.ColumnTypes
.SONG_ID
, out song_id
);
372 MPD
.PlayQueue
.set_priority(server
, song_id
, 0);
377 // Remove the selected songs from the play queue.
378 private bool selected_songs_remove()
380 int deleted_rows
= 0;
381 var selection
= this
.get_selection();
384 foreach(var path
in selection
.get_selected_rows(out model
))
387 if(model
.get_iter(out iter
, path
))
390 model
.get(iter
,Gmpc
.MpdData
.ColumnTypes
.SONG_ID
, out song_id
);
391 MPD
.PlayQueue
.queue_delete_id(server
, song_id
);
395 MPD
.PlayQueue
.queue_commit(server
);
396 return (deleted_rows
> 0);