Subversion Repositories winbugtracker

Rev

Rev 11 | Rev 13 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 daniel-mar 1
unit BugtrackerMain;
2
 
3
(*
4
 * TODO:
5 daniel-mar 5
 * - Spezielle Filter
6
 *   ... Auflisten nach Modul
7
 *   ... Anzeigen der Agenda
11 daniel-mar 8
 * - rtf control bar?
9
 * - ein neu angelegter bug soll links aus der leiste verschwinden, wenn er nicht in das kriterium passt
7 daniel-mar 10
 *
11
 * NOT INCLUDED:
12
 * - duplicate of
13
 *
14
 * FUTURE:
15
 * - HS Info integration
4 daniel-mar 16
 *)
17
 
18
interface
19
 
20
uses
21
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
6 daniel-mar 22
  Dialogs, WideStrings, DB, SqlExpr, StdCtrls, ExtCtrls, DBCtrls,
4 daniel-mar 23
  ADODB, ComCtrls, Grids, DBGrids, Mask, Menus, XPMan;
24
 
25
type
26
  TfrmBugtracker = class(TForm)
27
    Panel1: TPanel;
28
    DBGrid1: TDBGrid;
29
    ComboBox1: TComboBox;
30
    DBNavigator2: TDBNavigator;
31
    Panel2: TPanel;
32
    Label1: TLabel;
33
    Label2: TLabel;
34
    Label3: TLabel;
35
    Label4: TLabel;
36
    Label5: TLabel;
37
    Label6: TLabel;
38
    DBNavigator1: TDBNavigator;
39
    DBRichEdit1: TDBRichEdit;
40
    DBEdit1: TDBEdit;
41
    DBLookupComboBox1: TDBLookupComboBox;
42
    DBEdit2: TDBEdit;
43
    DBEdit3: TDBEdit;
44
    DBLookupComboBox2: TDBLookupComboBox;
45
    DBLookupComboBox3: TDBLookupComboBox;
46
    TrackBar1: TTrackBar;
47
    ADOConnection1: TADOConnection;
48
    dsBugs: TDataSource;
49
    tblMitarbeiter: TADOTable;
50
    dsMitarbeiter: TDataSource;
51
    MainMenu1: TMainMenu;
52
    Stammdaten1: TMenuItem;
53
    Mitarbeiter1: TMenuItem;
54
    Projekte1: TMenuItem;
55
    Module1: TMenuItem;
56
    Versionen1: TMenuItem;
57
    Projektwechseln1: TMenuItem;
58
    XPManifest1: TXPManifest;
59
    qryBugs: TADOQuery;
60
    dsVersionen: TDataSource;
61
    tblProjekte: TADOTable;
62
    dsProjekte: TDataSource;
63
    dsModule: TDataSource;
64
    Timer1: TTimer;
65
    Splitter1: TSplitter;
66
    Hilfe1: TMenuItem;
67
    ber1: TMenuItem;
68
    btnBearbeitungsnotiz: TButton;
69
    qryBugsid: TAutoIncField;
70
    qryBugstitel: TStringField;
71
    qryBugsbeschreibung: TMemoField;
72
    qryBugserstellt: TDateTimeField;
73
    qryBugswichtigkeit: TIntegerField;
74
    qryBugsbearbeiter: TIntegerField;
75
    qryBugsversion_release: TIntegerField;
76
    qryBugsmodul: TIntegerField;
77
    qryBugsprojekt: TIntegerField;
78
    qryVersionen: TADOQuery;
79
    qryModule: TADOQuery;
5 daniel-mar 80
    LblAngemeldet: TLabel;
81
    Label7: TLabel;
82
    Label8: TLabel;
6 daniel-mar 83
    DBLookupComboBox4: TDBLookupComboBox;
84
    qryBugserfasser: TIntegerField;
85
    qryBugsversion_agenda: TIntegerField;
86
    Label9: TLabel;
87
    cbxErfasser: TDBLookupComboBox;
88
    Label10: TLabel;
11 daniel-mar 89
    lkpStatus: TADOTable;
90
    dsStatus: TDataSource;
91
    DBLookupComboBox5: TDBLookupComboBox;
92
    qryBugsstatus: TIntegerField;
93
    qryBugsstatus_geaendert: TDateTimeField;
12 daniel-mar 94
    Bugs1: TMenuItem;
95
    Wechselnzu1: TMenuItem;
4 daniel-mar 96
    procedure Mitarbeiter1Click(Sender: TObject);
97
    procedure qryBugsAfterScroll(DataSet: TDataSet);
98
    procedure Module1Click(Sender: TObject);
99
    procedure Projekte1Click(Sender: TObject);
100
    procedure Versionen1Click(Sender: TObject);
101
    procedure TrackBar1Change(Sender: TObject);
102
    procedure Timer1Timer(Sender: TObject);
103
    procedure ComboBox1Change(Sender: TObject);
104
    procedure Projektwechseln1Click(Sender: TObject);
105
    procedure qryBugsAfterInsert(DataSet: TDataSet);
106
    procedure ber1Click(Sender: TObject);
107
    procedure qryBugsversion_releaseValidate(Sender: TField);
108
    procedure FormCreate(Sender: TObject);
109
    procedure qryVersionenAfterInsert(DataSet: TDataSet);
110
    procedure qryModuleAfterInsert(DataSet: TDataSet);
5 daniel-mar 111
    procedure btnBearbeitungsnotizClick(Sender: TObject);
8 daniel-mar 112
    procedure qryBugsBeforeCancel(DataSet: TDataSet);
113
    procedure DBNavigator1BeforeAction(Sender: TObject; Button: TNavigateBtn);
114
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
11 daniel-mar 115
    procedure qryBugsstatusChange(Sender: TField);
12 daniel-mar 116
    procedure Wechselnzu1Click(Sender: TObject);
4 daniel-mar 117
  public
118
    eingeloggtMitarbeiter: integer;
5 daniel-mar 119
    eingeloggtMitarbeiterName: string;
4 daniel-mar 120
    aktuellesProjekt: integer;
5 daniel-mar 121
    aktuellesProjektName: string;
4 daniel-mar 122
    procedure NeuFiltern;
5 daniel-mar 123
    procedure NotizHinzufuegen(color: TColor; bez: string);
4 daniel-mar 124
  end;
125
 
126
var
127
  frmBugtracker: TfrmBugtracker;
128
 
129
implementation
130
 
131
uses Mitarbeiter, Module, Versionen, Projekte, Login, About, inifiles;
132
 
133
{$R *.dfm}
134
 
135
procedure TfrmBugtracker.qryBugsAfterInsert(DataSet: TDataSet);
136
begin
137
  // Standardwerte für einen neuen Bug
6 daniel-mar 138
  qryBugs.FieldByName('wichtigkeit').AsInteger := 5; // Mitte
139
  qryBugs.FieldByName('erstellt').AsDateTime := Now;
140
  qryBugs.FieldByName('erfasser').AsInteger := eingeloggtMitarbeiter;
4 daniel-mar 141
  qryBugs.FieldByName('projekt').AsInteger := aktuellesProjekt;
11 daniel-mar 142
  qryBugs.FieldByName('status').AsInteger := 1; // Offen
4 daniel-mar 143
end;
144
 
145
procedure TfrmBugtracker.qryBugsAfterScroll(DataSet: TDataSet);
146
var
147
  bakEvent: TNotifyEvent;
148
begin
149
  bakEvent := TrackBar1.OnChange;
150
  TrackBar1.OnChange := nil;
151
  try
152
    TrackBar1.Position := qryBugs.FieldByName('wichtigkeit').AsInteger;
153
  finally
154
    TrackBar1.OnChange := bakEvent;
155
  end;
156
end;
157
 
8 daniel-mar 158
procedure TfrmBugtracker.qryBugsBeforeCancel(DataSet: TDataSet);
159
var
160
  abfrage: Integer;
161
begin
162
  // Tag 1 = Es wurde der "Abbrechen"-Knopf im DBNavigator gedrückt, also wollen wir keine unnötige Bestätigung
163
  // Alles andere = Irgendwas anderes (z.B. Scrolling oder versehentlich versucht das Fenster zu schließen)
164
  if qryBugs.Tag = 1 then exit;
165
 
166
  abfrage := MessageDlg('Speichern?', mtConfirmation, mbYesNoCancel, 0);
167
 
168
  if (abfrage = IDNo) or (abfrage = IDYes) or (abfrage = IDOK) then
169
  begin
170
     if abfrage = IDYes then
171
     begin
172
       if (qryBugs.state in [dsEdit, dsInsert]) then qryBugs.Post;
173
     end;
174
     if abfrage = IDNo then
175
     begin
176
       // Wir befinden uns bereits in qryBugs.Cancel, daher auskommentiert.
177
       // if (qryBugs.state in [dsEdit, dsInsert]) then qryBugs.Cancel;
178
     end;
179
  end
180
  else raise EAbort.Create('Abbruch durch Benutzer'); // Cancel geklickt
181
end;
182
 
11 daniel-mar 183
procedure TfrmBugtracker.qryBugsstatusChange(Sender: TField);
184
var
185
  col: TColor;
186
begin
187
  qryBugsstatus_geaendert.AsDateTime := Now;
188
 
189
  DBLookupComboBox5.KeyValue := qryBugsstatus.AsVariant; // nur benötigt, daamit wir auf DBLookupComboBox5.Text zugreifen können
190
  case qryBugsstatus.AsInteger of
12 daniel-mar 191
    // TODO: farben in db?
11 daniel-mar 192
    1: col := clRed; // Offen
193
    2: col := clMaroon; // Abgelehnt
194
    3: col := clPurple; // In Bearbeitung
195
    4: col := clTeal; // Gefixt
196
    5: col := clGreen; // Veröffentlicht
197
    else
198
      col := clBlack; // sollte nicht passieren
199
  end;
200
  NotizHinzufuegen(col, DBLookupComboBox5.Text);
201
end;
202
 
4 daniel-mar 203
procedure TfrmBugtracker.qryBugsversion_releaseValidate(Sender: TField);
204
begin
11 daniel-mar 205
  if qryBugs.FieldByName('status').AsInteger <> 5 then
4 daniel-mar 206
  begin
11 daniel-mar 207
    // raise Exception.Create('Vor einer Veröffentlichung muss der Bugfix erst als "Veröffentlicht" markiert werden.');
208
    qryBugs.FieldByName('status').AsInteger := 5;
4 daniel-mar 209
  end;
210
end;
211
 
212
procedure TfrmBugtracker.qryModuleAfterInsert(DataSet: TDataSet);
213
begin
214
  // Standardwerte für ein neues Modul
215
  qryModule.FieldByName('projekt').AsInteger := aktuellesProjekt;
216
end;
217
 
218
procedure TfrmBugtracker.qryVersionenAfterInsert(DataSet: TDataSet);
219
begin
220
  // Standardwerte für eine neue Version
221
  qryVersionen.FieldByName('projekt').AsInteger := aktuellesProjekt;
222
end;
223
 
224
procedure TfrmBugtracker.Timer1Timer(Sender: TObject);
225
begin
226
  Timer1.Enabled := false;
227
  if frmLogin.ShowModal = mrCancel then Close;
228
end;
229
 
230
procedure TfrmBugtracker.TrackBar1Change(Sender: TObject);
231
begin
232
  if not (qryBugs.State in [dsEdit, dsInsert]) then qryBugs.Edit;
233
  qryBugs.FieldByName('wichtigkeit').AsInteger := TrackBar1.Position;
234
end;
235
 
236
procedure TfrmBugtracker.Versionen1Click(Sender: TObject);
237
begin
238
  frmVersionen.ShowModal;
239
end;
240
 
12 daniel-mar 241
procedure TfrmBugtracker.Wechselnzu1Click(Sender: TObject);
242
var
243
  s: string;
244
  id, ec: integer;
245
begin
246
  s := Trim(InputBox('Wechseln zu Bug', 'ID des Bugs eingeben', '0'));
247
  if s = '' then exit;  
248
  Val(s, id, ec);
249
  if ec <> 0 then
250
  begin
251
    ShowMessageFmt('"%s" ist keine gültige Bug-ID-Nummer.', [id]);
252
    exit;
253
  end;
254
  qryBugs.Locate('id', id, []);
255
end;
256
 
4 daniel-mar 257
procedure TfrmBugtracker.ber1Click(Sender: TObject);
258
begin
259
  AboutBox.ShowModal;
260
end;
261
 
5 daniel-mar 262
procedure TfrmBugtracker.btnBearbeitungsnotizClick(Sender: TObject);
263
begin
11 daniel-mar 264
  NotizHinzufuegen(clOlive, 'Notiz');
5 daniel-mar 265
end;
266
 
4 daniel-mar 267
procedure TfrmBugtracker.ComboBox1Change(Sender: TObject);
268
begin
269
  case ComboBox1.ItemIndex of
270
    0:
271
      begin
272
        // Meine offenen Bugs (nach Wichtigkeit)
11 daniel-mar 273
        qryBugs.SQL.Text := 'SELECT * FROM bugs WHERE projekt = '+IntToStr(aktuellesProjekt)+' AND (status = 1 OR status = 3) AND bearbeiter = '+IntToStr(eingeloggtMitarbeiter)+' ORDER BY wichtigkeit DESC';
4 daniel-mar 274
      end;
275
    1:
276
      begin
277
        // Alle offenen Bugs (nach Wichtigkeit)
11 daniel-mar 278
        qryBugs.SQL.Text := 'SELECT * FROM bugs WHERE projekt = '+IntToStr(aktuellesProjekt)+' AND (status = 1 OR status = 3) ORDER BY wichtigkeit DESC';
4 daniel-mar 279
      end;
280
    2:
281
      begin
282
        // Gelöst ohne Veröffentlichung (nach Lösungsdatum)
11 daniel-mar 283
        qryBugs.SQL.Text := 'SELECT * FROM bugs WHERE projekt = '+IntToStr(aktuellesProjekt)+' AND status = 4 ORDER BY status_geaendert DESC';
4 daniel-mar 284
      end;
285
    3:
286
      begin
287
        // Gelöst und Veröffentlicht (nach Version und Lösungsdatum)
11 daniel-mar 288
        qryBugs.SQL.Text := 'SELECT * FROM bugs WHERE projekt = '+IntToStr(aktuellesProjekt)+' AND status = 5 ORDER BY status_geaendert DESC';
4 daniel-mar 289
      end;
290
    4:
291
      begin
292
        // Alle Bugs (nach Eröffnungsdatum)
293
        qryBugs.SQL.Text := 'SELECT * FROM bugs WHERE projekt = '+IntToStr(aktuellesProjekt)+' ORDER BY erstellt DESC';
294
      end;
295
  end;
296
  qryBugs.Active := true;
297
end;
298
 
8 daniel-mar 299
procedure TfrmBugtracker.DBNavigator1BeforeAction(Sender: TObject; Button: TNavigateBtn);
300
begin
301
  if Button = nbCancel then
302
  begin
303
    if qryBugs.state  in [dsEdit,dsInsert] then
304
    begin
305
      // Tag=1 soll verhindern, dass nicht gefragt wird, ob man Speichern möchte.
306
      // Ansonsten würde diese Meldung kommen, denn ".Cancel" wird automatisch
307
      // bei Ereignissen wie z.B. dem Scrolling aufgerufen (noch bevor
308
      // OnBeforeScroll aufgerufen wird), bei dem man einen MBOnCloseQuery wünscht.
309
      qryBugs.Tag := 1;
310
      qryBugs.Cancel;
311
      qryBugs.Tag := 0;
312
    end;
313
  end;
314
end;
315
 
316
procedure TfrmBugtracker.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
317
begin
318
  qryBugs.Cancel;
319
end;
320
 
4 daniel-mar 321
procedure TfrmBugtracker.FormCreate(Sender: TObject);
322
var
323
  ini: TMemIniFile;
324
begin
325
  ini := TMemIniFile.Create('bugtracker.ini');
326
  try
6 daniel-mar 327
    ADOConnection1.Connected := false;
4 daniel-mar 328
    ADOConnection1.ConnectionString := ini.ReadString('Database', 'ConnectionString', '');
329
  finally
330
    ini.Free;
331
  end;
332
 
333
  ADOConnection1.Connected := true;
334
  qryBugs.Active := true;
335
  tblMitarbeiter.Active := true;
336
  qryVersionen.Active := true;
337
  tblProjekte.Active := true;
338
  qryModule.Active := true;
11 daniel-mar 339
  lkpStatus.Active := true;
4 daniel-mar 340
end;
341
 
342
procedure TfrmBugtracker.Mitarbeiter1Click(Sender: TObject);
343
begin
344
  frmMitarbeiter.ShowModal;
345
end;
346
 
347
procedure TfrmBugtracker.Module1Click(Sender: TObject);
348
begin
349
  frmModule.ShowModal;
350
end;
351
 
352
procedure TfrmBugtracker.NeuFiltern;
353
begin
354
  ComboBox1Change(ComboBox1);
355
 
356
  qryModule.SQL.Text := 'SELECT * FROM module WHERE projekt = ' + IntToStr(aktuellesProjekt);
357
  qryModule.Active := true;
358
 
359
  qryVersionen.SQL.Text := 'SELECT * FROM versionen WHERE projekt = ' + IntToStr(aktuellesProjekt);
360
  qryVersionen.Active := true;
361
end;
362
 
5 daniel-mar 363
procedure TfrmBugtracker.NotizHinzufuegen(color: TColor; bez: string);
364
var
365
  leerzeilen: integer;
366
  umbruch: string;
367
  prefix: string;
368
begin
369
  if not (qryBugs.State in [dsEdit, dsInsert]) then qryBugs.Edit;
370
 
371
  // Endet der Text mit zwei Zeilenabständen? Wenn nein, dann einfügen.
11 daniel-mar 372
  if Trim(DBRichEdit1.Text) <> '' then
373
  begin
374
    leerzeilen := 0;
375
    if Copy(DBRichEdit1.Text, 1+Length(DBRichEdit1.Text)-2, 2) = #13#10 then Inc(leerzeilen); // letzte Zeile
376
    if Copy(DBRichEdit1.Text, 1+Length(DBRichEdit1.Text)-4, 2) = #13#10 then Inc(leerzeilen); // Vorletzte Zeile
377
    case leerzeilen of
378
      0: umbruch := #13#10#13#10;
379
      1: umbruch := #13#10;
380
      2: umbruch := '';
381
    end;
382
  end
383
  else
384
  begin
385
    umbruch := '';
5 daniel-mar 386
  end;
387
 
388
  DBRichEdit1.SelStart := DBRichEdit1.GetTextLen;
389
  DBRichEdit1.SelText := umbruch;
390
 
391
  DBRichEdit1.SelAttributes.Size := 13;
392
  DBRichEdit1.SelAttributes.Color := color;
393
  DBRichEdit1.SelAttributes.Style := [fsUnderline];
394
  if Trim(bez) <> '' then
395
    prefix := Trim(bez) + ' - '
396
  else
397
    prefix := '';
398
  DBRichEdit1.SelText := prefix + eingeloggtMitarbeiterName + ' ' + FormatDateTime('dd.mm.yyyy hh:nn', Now); // DateTimeToStr(Now);
399
 
400
  DBRichEdit1.SelAttributes.Size := 10;
401
  DBRichEdit1.SelAttributes.Color := clWindowText;
402
  DBRichEdit1.SelAttributes.Style := [];
403
  DBRichEdit1.SelText := #13#10 {+ '<Hier Text eingeben>'};
404
 
405
  // Ans Ende scrollen
406
  DBRichEdit1.SetFocus;
407
  DBRichEdit1.SelStart := DBRichEdit1.GetTextLen;
408
  DBRichEdit1.Perform(EM_SCROLLCARET, 0, 0);
409
end;
410
 
4 daniel-mar 411
procedure TfrmBugtracker.Projekte1Click(Sender: TObject);
412
begin
413
  frmProjekte.ShowModal;
414
end;
415
 
416
procedure TfrmBugtracker.Projektwechseln1Click(Sender: TObject);
417
begin
418
  frmLogin.ShowModal;
419
end;
420
 
421
end.